Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886/* * Copyright (c) 2006, 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */
#include <sys/cdefs.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <strings.h>#include <stdlib.h>#include <sys/errno.h>#include <sys/msgbuf.h>#include <sys/resource.h>#include <sys/process_policy.h>#include <sys/event.h>#include <mach/message.h>
#include "libproc_internal.h"
int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);__private_extern__ int proc_setthreadname(void * buffer, int buffersize);int __process_policy(int scope, int action, int policy, int policy_subtype, proc_policy_attribute_t * attrp, pid_t target_pid, uint64_t target_threadid);int proc_rlimit_control(pid_t pid, int flavor, void *arg);
int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize) { int retval; if ((type >= PROC_ALL_PIDS) || (type <= PROC_PPID_ONLY)) { if ((retval = __proc_info(PROC_INFO_CALL_LISTPIDS, type, typeinfo,(uint64_t)0, buffer, buffersize)) == -1) return(0); } else { errno = EINVAL; retval = 0; } return(retval);}
int proc_listallpids(void * buffer, int buffersize){ int numpids; numpids = proc_listpids(PROC_ALL_PIDS, (uint32_t)0, buffer, buffersize);
if (numpids == -1) return(-1); else return(numpids/sizeof(int));}
int proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize){ int numpids; numpids = proc_listpids(PROC_PGRP_ONLY, (uint32_t)pgrpid, buffer, buffersize); if (numpids == -1) return(-1); else return(numpids/sizeof(int));}
int proc_listchildpids(pid_t ppid, void * buffer, int buffersize){ int numpids; numpids = proc_listpids(PROC_PPID_ONLY, (uint32_t)ppid, buffer, buffersize); if (numpids == -1) return(-1); else return(numpids/sizeof(int));}
int proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor, arg, buffer, buffersize)) == -1) return(0); return(retval);}
int proc_pidoriginatorinfo(int flavor, void *buffer, int buffersize){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_PIDORIGINATORINFO, getpid(), flavor, 0, buffer, buffersize)) == -1) return(0); return(retval);}
intproc_listcoalitions(int flavor, int coaltype, void *buffer, int buffersize){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_LISTCOALITIONS, flavor, coaltype, 0, buffer, buffersize)) == -1) return 0;
return retval;}
intproc_pid_rusage(int pid, int flavor, rusage_info_t *buffer){ return (__proc_info(PROC_INFO_CALL_PIDRUSAGE, pid, flavor, 0, buffer, 0));}
intproc_setthread_cpupercent(uint8_t percentage, uint32_t ms_refill){ uint32_t arg = 0;
/* Pack percentage and refill into a 32-bit number to match existing kernel implementation */ if ((percentage >= 100) || (ms_refill & ~0xffffffU)) { errno = EINVAL; return -1; }
arg = ((ms_refill << 8) | percentage);
return (proc_rlimit_control(-1, RLIMIT_THREAD_CPULIMITS, (void *)(uintptr_t)arg));}
int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, flavor, (uint64_t)fd, buffer, buffersize)) == -1) return(0); return (retval);}
intproc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_PIDFILEPORTINFO, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1) return (0); return (retval);}
intproc_name(int pid, void * buffer, uint32_t buffersize){ int retval = 0, len; struct proc_bsdinfo pbsd; if (buffersize < sizeof(pbsd.pbi_name)) { errno = ENOMEM; return(0); }
retval = proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &pbsd, sizeof(struct proc_bsdinfo)); if (retval != 0) { if (pbsd.pbi_name[0]) { bcopy(&pbsd.pbi_name, buffer, sizeof(pbsd.pbi_name)); } else { bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm)); } len = (int)strlen(buffer); return(len); } return(0);}
int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize){ int retval = 0, len; struct proc_regionwithpathinfo reginfo; if (buffersize < MAXPATHLEN) { errno = ENOMEM; return(0); } retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, ®info, sizeof(struct proc_regionwithpathinfo)); if (retval != -1) { len = (int)strlen(®info.prp_vip.vip_path[0]); if (len != 0) { if (len > MAXPATHLEN) len = MAXPATHLEN; bcopy(®info.prp_vip.vip_path[0], buffer, len); return(len); } return(0); } return(0); }
intproc_kmsgbuf(void * buffer, uint32_t buffersize){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_KERNMSGBUF, 0, 0, (uint64_t)0, buffer, buffersize)) == -1) return(0); return (retval);}
intproc_pidpath(int pid, void * buffer, uint32_t buffersize){ int retval, len;
if (buffersize < PROC_PIDPATHINFO_SIZE) { errno = ENOMEM; return(0); } if (buffersize > PROC_PIDPATHINFO_MAXSIZE) { errno = EOVERFLOW; return(0); }
retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize); if (retval != -1) { len = (int)strlen(buffer); return(len); } return (0);}
int proc_libversion(int *major, int * minor){
if (major != NULL) *major = 1; if (minor != NULL) *minor = 1; return(0);}
intproc_setpcontrol(const int control){ int retval ;
if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE) return(EINVAL);
if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1) return(errno); return(0);}
__private_extern__ intproc_setthreadname(void * buffer, int buffersize){ int retval;
retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize);
if (retval == -1) return(errno); else return(0);}
intproc_track_dirty(pid_t pid, uint32_t flags){ if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_TRACK, flags, NULL, 0) == -1) { return errno; } return 0;}
intproc_set_dirty(pid_t pid, bool dirty){ if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_SET, dirty, NULL, 0) == -1) { return errno; }
return 0;}
intproc_get_dirty(pid_t pid, uint32_t *flags){ int retval; if (!flags) { return EINVAL; } retval = __proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_GET, 0, NULL, 0); if (retval == -1) { return errno; } *flags = retval;
return 0;}
intproc_clear_dirty(pid_t pid, uint32_t flags){ if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_CLEAR, flags, NULL, 0) == -1) { return errno; }
return 0;}
intproc_terminate(pid_t pid, int *sig){ int retval; if (!sig) { return EINVAL; } retval = __proc_info(PROC_INFO_CALL_TERMINATE, pid, 0, 0, NULL, 0); if (retval == -1) { return errno; } *sig = retval; return 0;}
/* * XXX the _fatal() variant both checks for an existing monitor * (with important policy effects on first party background apps) * and validates inputs. */intproc_set_cpumon_params(pid_t pid, int percentage, int interval){ proc_policy_cpuusage_attr_t attr;
/* no argument validation ... * task_set_cpuusage() ignores 0 values and squashes negative * values into uint32_t. */
attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC; attr.ppattr_cpu_percentage = percentage; attr.ppattr_cpu_attr_interval = (uint64_t)interval; attr.ppattr_cpu_attr_deadline = 0;
return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));}
intproc_get_cpumon_params(pid_t pid, int *percentage, int *interval){ proc_policy_cpuusage_attr_t attr; int ret;
ret = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0);
if ((ret == 0) && (attr.ppattr_cpu_attr == PROC_POLICY_RSRCACT_NOTIFY_EXC)) { *percentage = attr.ppattr_cpu_percentage; *interval = (int)attr.ppattr_cpu_attr_interval; } else { *percentage = 0; *interval = 0; }
return (ret);}
intproc_set_cpumon_defaults(pid_t pid){ proc_policy_cpuusage_attr_t attr;
attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC; attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DEFAULTS; attr.ppattr_cpu_attr_interval = 0; attr.ppattr_cpu_attr_deadline = 0;
return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));}
intproc_resume_cpumon(pid_t pid){ return __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, 0);}
intproc_disable_cpumon(pid_t pid){ proc_policy_cpuusage_attr_t attr;
attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC; attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DISABLE; attr.ppattr_cpu_attr_interval = 0; attr.ppattr_cpu_attr_deadline = 0;
return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));}
/* * Turn on the CPU usage monitor using the supplied parameters, and make * violations of the monitor fatal. * * Returns: 0 on success; * -1 on failure and sets errno */intproc_set_cpumon_params_fatal(pid_t pid, int percentage, int interval){ int current_percentage = 0; int current_interval = 0; /* intervals are in seconds */ int ret = 0;
if ((percentage <= 0) || (interval <= 0)) { errno = EINVAL; return (-1); }
/* * Do a simple query to see if CPU monitoring is * already active. If either the percentage or the * interval is nonzero, then CPU monitoring is * already in use for this process. * * XXX: need set...() and set..fatal() to behave similarly. * Currently, this check prevents 1st party apps (which get a * default non-fatal monitor) not to get a fatal monitor. */ (void)proc_get_cpumon_params(pid, ¤t_percentage, ¤t_interval); if (current_percentage || current_interval) { /* * The CPU monitor appears to be active. * We choose not to disturb those settings. */ errno = EBUSY; return (-1); } if ((ret = proc_set_cpumon_params(pid, percentage, interval)) != 0) { /* Failed to activate the CPU monitor */ return (ret); } if ((ret = proc_rlimit_control(pid, RLIMIT_CPU_USAGE_MONITOR, CPUMON_MAKE_FATAL)) != 0) { /* Failed to set termination, back out the CPU monitor settings. */ (void)proc_disable_cpumon(pid); }
return (ret);}
intproc_set_wakemon_params(pid_t pid, int rate_hz, int flags __unused){ struct proc_rlimit_control_wakeupmon params;
params.wm_flags = WAKEMON_ENABLE; params.wm_rate = rate_hz;
return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms));}
#ifndef WAKEMON_GET_PARAMS#define WAKEMON_GET_PARAMS 0x4#define WAKEMON_SET_DEFAULTS 0x8#endif
intproc_get_wakemon_params(pid_t pid, int *rate_hz, int *flags){ struct proc_rlimit_control_wakeupmon params; int error;
params.wm_flags = WAKEMON_GET_PARAMS;
if ((error = proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms)) != 0) { return (error); }
*rate_hz = params.wm_rate; *flags = params.wm_flags;
return (0);}
intproc_set_wakemon_defaults(pid_t pid){ struct proc_rlimit_control_wakeupmon params;
params.wm_flags = WAKEMON_ENABLE | WAKEMON_SET_DEFAULTS; params.wm_rate = -1;
return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms));}
intproc_disable_wakemon(pid_t pid){ struct proc_rlimit_control_wakeupmon params;
params.wm_flags = WAKEMON_DISABLE; params.wm_rate = -1;
return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms));}
intproc_list_uptrs(int pid, uint64_t *buf, uint32_t bufsz){ int i, j; int nfds, nkns; int count = 0; int knote_max = 4096; /* arbitrary starting point */
/* if buffer is empty, this call simply counts the knotes */ if (bufsz > 0 && buf == NULL) { errno = EFAULT; return -1; }
/* get the list of FDs for this process */ struct proc_fdinfo fdlist[OPEN_MAX+1]; nfds = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, &fdlist[1], OPEN_MAX*sizeof(struct proc_fdinfo)); if (nfds < 0 || nfds > OPEN_MAX) { return -1; }
/* Add FD -1, the implicit workq kqueue */ fdlist[0].proc_fd = -1; fdlist[0].proc_fdtype = PROX_FDTYPE_KQUEUE; nfds++;
struct kevent_extinfo *kqext = malloc(knote_max * sizeof(struct kevent_extinfo)); if (!kqext) { errno = ENOMEM; return -1; }
for (i = 0; i < nfds; i++) { if (fdlist[i].proc_fdtype != PROX_FDTYPE_KQUEUE) { continue; }
again: nkns = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, PROC_PIDFDKQUEUE_EXTINFO, (uint64_t)fdlist[i].proc_fd, kqext, knote_max * sizeof(struct kevent_extinfo)); if (nkns < 0) { if (errno == EBADF) { /* the FD table can change after enumerating the FDs */ errno = EAGAIN; } free(kqext); return -1; }
if (nkns > knote_max) { /* there are more knotes than we requested - try again with a * larger buffer */ free(kqext); knote_max = nkns + 32; /* small margin in case of extra knotes */ kqext = malloc(knote_max * sizeof(struct kevent_extinfo)); if (!kqext) { errno = ENOMEM; return -1; } goto again; }
for (j = 0; j < nkns; j++) { if (kqext[j].kqext_kev.udata == 0) { continue; }
if (bufsz >= sizeof(uint64_t)) { *buf++ = kqext[j].kqext_kev.udata; bufsz -= sizeof(uint64_t); } count++; } }
free(kqext); return count;}
/* Donate importance to adaptive processes from this process */int proc_donate_importance_boost(){ int rval;
rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_BOOST, PROC_POLICY_IMP_DONATION, NULL, getpid(), 0);
if (rval == 0) return (0); else return (errno);}
static __attribute__((noinline)) voidproc_importance_bad_assertion(char *reason) { (void)reason;}
/* * Use the address of these variables as the token. This way, they can be * printed in the debugger as useful names. */uint64_t important_boost_assertion_token = 0xfafafafafafafafa;uint64_t normal_boost_assertion_token = 0xfbfbfbfbfbfbfbfb;uint64_t non_boost_assertion_token = 0xfcfcfcfcfcfcfcfc;uint64_t denap_boost_assertion_token = 0xfdfdfdfdfdfdfdfd;
/* * Accept the boost on a message, or request another boost assertion * if we have already accepted the implicit boost for this message. * * Returns EOVERFLOW if an attempt is made to take an extra assertion when not boosted. * * Returns EIO if the message was not a boosting message. * TODO: Return a 'non-boost' token instead. */intproc_importance_assertion_begin_with_msg(mach_msg_header_t *msg, __unused mach_msg_trailer_t *trailer, uint64_t *assertion_token){ int rval = 0;
if (assertion_token == NULL) return (EINVAL);
#define LEGACYBOOSTMASK (MACH_MSGH_BITS_VOUCHER_MASK | MACH_MSGH_BITS_RAISEIMP)#define LEGACYBOOSTED(m) (((m)->msgh_bits & LEGACYBOOSTMASK) == MACH_MSGH_BITS_RAISEIMP)
/* Is this a legacy boosted message? */ if (LEGACYBOOSTED(msg)) {
/* * Have we accepted the implicit boost for this message yet? * If we haven't accepted it yet, no need to call into kernel. */ if ((msg->msgh_bits & MACH_MSGH_BITS_IMPHOLDASRT) == 0) { msg->msgh_bits |= MACH_MSGH_BITS_IMPHOLDASRT; *assertion_token = (uint64_t) &important_boost_assertion_token; return (0); }
/* Request an additional boost count */ rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_HOLD, PROC_POLICY_BOOST, PROC_POLICY_IMP_IMPORTANT, NULL, getpid(), 0); if (rval == 0) { *assertion_token = (uint64_t) &important_boost_assertion_token; return (0); } else if (errno == EOVERFLOW) { proc_importance_bad_assertion("Attempted to take assertion while not boosted"); return (errno); } else { return (errno); } } return (EIO);}
/* * Drop a boost assertion. * Returns EOVERFLOW on boost assertion underflow. */intproc_importance_assertion_complete(uint64_t assertion_token){ int rval = 0;
if (assertion_token == 0) return (0);
if (assertion_token == (uint64_t) &important_boost_assertion_token) { rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DROP, PROC_POLICY_BOOST, PROC_POLICY_IMP_IMPORTANT, NULL, getpid(), 0); if (rval == 0) { return (0); } else if (errno == EOVERFLOW) { proc_importance_bad_assertion("Attempted to drop too many assertions"); return (errno); } else { return (errno); } } else { proc_importance_bad_assertion("Attempted to drop assertion with invalid token"); return (EIO); }}
/* * Accept the De-Nap boost on a message, or request another boost assertion * if we have already accepted the implicit boost for this message. * * Interface is deprecated before it really got started - just as synonym * for proc_importance_assertion_begin_with_msg() now. */intproc_denap_assertion_begin_with_msg(mach_msg_header_t *msg, uint64_t *assertion_token){#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations" return proc_importance_assertion_begin_with_msg(msg, NULL, assertion_token);#pragma clang diagnostic pop}
/* * Drop a denap boost assertion. * * Interface is deprecated before it really got started - just a synonym * for proc_importance_assertion_complete() now. */intproc_denap_assertion_complete(uint64_t assertion_token){ return proc_importance_assertion_complete(assertion_token);}
intproc_clear_vmpressure(pid_t pid){ if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_STARVATION, PROC_POLICY_RS_VIRTUALMEM, NULL, pid, (uint64_t)0) != -1) return(0); else return(errno);}
/* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */int proc_set_owner_vmpressure(void){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1) return(errno); return(0);}
/* mark yourself to delay idle sleep on disk IO */int proc_set_delayidlesleep(void){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)1, NULL, 0)) == -1) return(errno);
return(0);}
/* Reset yourself to delay idle sleep on disk IO, if already set */int proc_clear_delayidlesleep(void){ int retval;
if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)0, NULL, 0)) == -1) return(errno);
return(0);}
/* disable the launch time backgroudn policy and restore the process to default group */int proc_disable_apptype(pid_t pid, int apptype){ switch (apptype) { case PROC_POLICY_OSX_APPTYPE_TAL: case PROC_POLICY_OSX_APPTYPE_DASHCLIENT: break; default: return(EINVAL); }
if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1) return(0); else return(errno);
}
/* re-enable the launch time background policy if it had been disabled. */int proc_enable_apptype(pid_t pid, int apptype){ switch (apptype) { case PROC_POLICY_OSX_APPTYPE_TAL: case PROC_POLICY_OSX_APPTYPE_DASHCLIENT: break; default: return(EINVAL);
}
if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1) return(0); else return(errno); }
#if !TARGET_IPHONE_SIMULATOR
intproc_suppress(__unused pid_t pid, __unused uint64_t *generation){ return 0;}
#endif /* !TARGET_IPHONE_SIMULATOR */