+static uint32_t
+jetsam_task_page_count(task_t task)
+{
+ kern_return_t ret;
+ static task_info_data_t data;
+ static struct task_basic_info *info = (struct task_basic_info *)&data;
+ static mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
+
+ ret = task_info(task, TASK_BASIC_INFO, (task_info_t)&data, &count);
+ if (ret == KERN_SUCCESS) {
+ return info->resident_size / PAGE_SIZE;
+ }
+ return 0;
+}
+
+static uint32_t
+jetsam_flags_for_pid(pid_t pid)
+{
+ int i;
+
+ for (i = 0; i < jetsam_priority_list_count; i++) {
+ if (pid == jetsam_priority_list[i].pid) {
+ return jetsam_priority_list[i].flags;
+ }
+ }
+ return 0;
+}
+
+static void
+jetsam_snapshot_procs(void)
+{
+ proc_t p;
+ int i = 0;
+
+ jetsam_snapshot.stats.free_pages = vm_page_free_count;
+ jetsam_snapshot.stats.active_pages = vm_page_active_count;
+ jetsam_snapshot.stats.inactive_pages = vm_page_inactive_count;
+ jetsam_snapshot.stats.purgeable_pages = vm_page_purgeable_count;
+ jetsam_snapshot.stats.wired_pages = vm_page_wire_count;
+ proc_list_lock();
+ LIST_FOREACH(p, &allproc, p_list) {
+ task_t task = p->task;
+ jetsam_snapshot_list[i].pid = p->p_pid;
+ jetsam_snapshot_list[i].pages = jetsam_task_page_count(task);
+ jetsam_snapshot_list[i].flags = jetsam_flags_for_pid(p->p_pid);
+ strlcpy(&jetsam_snapshot_list[i].name[0], p->p_comm, MAXCOMLEN+1);
+#ifdef DEBUG
+ printf("jetsam snapshot pid = %d, uuid = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ p->p_pid,
+ p->p_uuid[0], p->p_uuid[1], p->p_uuid[2], p->p_uuid[3], p->p_uuid[4], p->p_uuid[5], p->p_uuid[6], p->p_uuid[7],
+ p->p_uuid[8], p->p_uuid[9], p->p_uuid[10], p->p_uuid[11], p->p_uuid[12], p->p_uuid[13], p->p_uuid[14], p->p_uuid[15]);
+#endif
+ memcpy(&jetsam_snapshot_list[i].uuid[0], &p->p_uuid[0], sizeof(p->p_uuid));
+ i++;
+ if (i == kMaxSnapshotEntries) {
+ break;
+ }
+ }
+ proc_list_unlock();
+ jetsam_snapshot.entry_count = jetsam_snapshot_list_count = i - 1;
+}
+
+static void
+jetsam_mark_pid_in_snapshot(pid_t pid)
+{
+
+ int i = 0;
+
+ for (i = 0; i < jetsam_snapshot_list_count; i++) {
+ if (jetsam_snapshot_list[i].pid == pid) {
+ jetsam_snapshot_list[i].flags |= kJetsamFlagsKilled;
+ return;
+ }
+ }
+}
+
+static int
+jetsam_kill_top_proc(void)
+{
+ proc_t p;
+
+ if (jetsam_snapshot_list_count == 0) {
+ jetsam_snapshot_procs();
+ }
+ lck_mtx_lock(jetsam_list_mlock);
+ while (jetsam_priority_list_index < jetsam_priority_list_count) {
+ pid_t aPid;
+ aPid = jetsam_priority_list[jetsam_priority_list_index].pid;
+ jetsam_priority_list_index++;
+ /* skip empty slots in the list */
+ if (aPid == 0) {
+ continue; // with lock held
+ }
+ lck_mtx_unlock(jetsam_list_mlock);
+ jetsam_mark_pid_in_snapshot(aPid);
+ p = proc_find(aPid);
+ if (p != NULL) {
+#if DEBUG
+ printf("jetsam: killing pid %d [%s] - memory_status_level: %d - ", aPid, p->p_comm, kern_memorystatus_level);
+#endif /* DEBUG */
+ exit1(p, W_EXITCODE(0, SIGKILL), (int *)NULL);
+ proc_rele(p);
+#if DEBUG
+ printf("jetsam: pid %d killed - memory_status_level: %d\n", aPid, kern_memorystatus_level);
+#endif /* DEBUG */
+ return 0;
+ }
+ lck_mtx_lock(jetsam_list_mlock);
+ }
+ lck_mtx_unlock(jetsam_list_mlock);
+ return -1;
+}
+