+ last_no_space_action = now;
+ memorystatus_kill_on_VM_thrashing(TRUE /* async */);
+ return (1);
+ }
+
+ /*
+ * No eligible processes to kill. So let's suspend/kill the largest
+ * process depending on its policy control specifications.
+ */
+
+ if (nps.pcs_max_size > 0) {
+ if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) {
+
+ if (nps.pcs_uniqueid == p->p_uniqueid) {
+ /*
+ * verify this is still the same process
+ * in case the proc exited and the pid got reused while
+ * we were finishing the proc_iterate and getting to this point
+ */
+ last_no_space_action = now;
+
+ proc_dopcontrol(p);
+
+ proc_rele(p);
+
+ return (1);
+ }
+
+ proc_rele(p);
+ }
+ }
+ last_no_space_action = now;
+
+ printf("low swap: unable to find any eligible processes to take action on\n");
+
+ return (0);
+}
+
+int
+proc_trace_log(__unused proc_t p, struct proc_trace_log_args *uap, __unused int *retval)
+{
+ int ret = 0;
+ proc_t target_proc = PROC_NULL;
+ pid_t target_pid = uap->pid;
+ uint64_t target_uniqueid = uap->uniqueid;
+ task_t target_task = NULL;
+
+ if (priv_check_cred(kauth_cred_get(), PRIV_PROC_TRACE_INSPECT, 0)) {
+ ret = EPERM;
+ goto out;
+ }
+ target_proc = proc_find(target_pid);
+ if (target_proc != PROC_NULL) {
+ if (target_uniqueid != proc_uniqueid(target_proc)) {
+ ret = ENOENT;
+ goto out;
+ }
+
+ target_task = proc_task(target_proc);
+ if (task_send_trace_memory(target_task, target_pid, target_uniqueid)) {
+ ret = EINVAL;
+ goto out;
+ }
+ } else
+ ret = ENOENT;
+
+out:
+ if (target_proc != PROC_NULL)
+ proc_rele(target_proc);
+ return (ret);
+}
+
+#if VM_SCAN_FOR_SHADOW_CHAIN
+extern int vm_map_shadow_max(vm_map_t map);
+int proc_shadow_max(void);
+int proc_shadow_max(void)
+{
+ int retval, max;
+ proc_t p;
+ task_t task;
+ vm_map_t map;
+
+ max = 0;
+ proc_list_lock();
+ for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
+ if (p->p_stat == SIDL)
+ continue;
+ task = p->task;
+ if (task == NULL) {
+ continue;
+ }
+ map = get_task_map(task);
+ if (map == NULL) {
+ continue;
+ }
+ retval = vm_map_shadow_max(map);
+ if (retval > max) {
+ max = retval;
+ }
+ }
+ proc_list_unlock();
+ return max;
+}
+#endif /* VM_SCAN_FOR_SHADOW_CHAIN */
+
+void proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid);
+void proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid)
+{
+ if (target_proc != NULL) {
+ target_proc->p_responsible_pid = responsible_pid;
+ }
+ return;
+}
+
+int
+proc_chrooted(proc_t p)
+{
+ int retval = 0;
+
+ if (p) {
+ proc_fdlock(p);
+ retval = (p->p_fd->fd_rdir != NULL) ? 1 : 0;
+ proc_fdunlock(p);
+ }
+
+ return retval;
+}
+
+void *
+proc_get_uthread_uu_threadlist(void * uthread_v)
+{
+ uthread_t uth = (uthread_t)uthread_v;
+ return (uth != NULL) ? uth->uu_threadlist : NULL;
+}
+
+#ifdef CONFIG_32BIT_TELEMETRY
+void
+proc_log_32bit_telemetry(proc_t p)
+{
+ /* Gather info */
+ char signature_buf[MAX_32BIT_EXEC_SIG_SIZE] = { 0 };
+ char * signature_cur_end = &signature_buf[0];
+ char * signature_buf_end = &signature_buf[MAX_32BIT_EXEC_SIG_SIZE - 1];
+ int bytes_printed = 0;
+
+ const char * teamid = NULL;
+ const char * identity = NULL;
+ struct cs_blob * csblob = NULL;
+
+ proc_list_lock();
+
+ /*
+ * Get proc name and parent proc name; if the parent execs, we'll get a
+ * garbled name.
+ */
+ bytes_printed = snprintf(signature_cur_end,
+ signature_buf_end - signature_cur_end,
+ "%s,%s,", p->p_name,
+ (p->p_pptr ? p->p_pptr->p_name : ""));
+
+ if (bytes_printed > 0) {
+ signature_cur_end += bytes_printed;
+ }
+
+ proc_list_unlock();
+
+ /* Get developer info. */
+ vnode_t v = proc_getexecutablevnode(p);
+
+ if (v) {
+ csblob = csvnode_get_blob(v, 0);
+
+ if (csblob) {
+ teamid = csblob_get_teamid(csblob);
+ identity = csblob_get_identity(csblob);