X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..cc8bc92ae4a8e9f1a1ab61bf83d34ad8150b3405:/libsyscall/wrappers/libproc/libproc.c?ds=inline diff --git a/libsyscall/wrappers/libproc/libproc.c b/libsyscall/wrappers/libproc/libproc.c index fa0b8c16e..255664d9c 100644 --- a/libsyscall/wrappers/libproc/libproc.c +++ b/libsyscall/wrappers/libproc/libproc.c @@ -26,11 +26,12 @@ #include #include #include +#include #include #include #include -#define BUILD_LIBSYSCALL 1 #include +#include #include #include "libproc_internal.h" @@ -102,12 +103,51 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize) 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); +} + +int +proc_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; +} + int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) { return (__proc_info(PROC_INFO_CALL_PIDRUSAGE, pid, flavor, 0, buffer, 0)); } +int +proc_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) { @@ -130,6 +170,17 @@ proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int b return (retval); } +int +proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer, int buffersize) +{ + int ret; + + if ((ret = __proc_info(PROC_INFO_CALL_PIDDYNKQUEUEINFO, pid, flavor, (uint64_t)kq_id, buffer, buffersize)) == -1) { + return 0; + } + + return ret; +} int proc_name(int pid, void * buffer, uint32_t buffersize) @@ -150,7 +201,7 @@ proc_name(int pid, void * buffer, uint32_t buffersize) } else { bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm)); } - len = strlen(buffer); + len = (int)strlen(buffer); return(len); } return(0); @@ -159,7 +210,7 @@ proc_name(int pid, void * buffer, uint32_t buffersize) int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize) { - int retval = 0, len; + int retval; struct proc_regionwithpathinfo reginfo; if (buffersize < MAXPATHLEN) { @@ -169,17 +220,9 @@ proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersiz retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, ®info, sizeof(struct proc_regionwithpathinfo)); if (retval != -1) { - len = 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 ((int)(strlcpy(buffer, reginfo.prp_vip.vip_path, MAXPATHLEN))); } - return(0); - + return(0); } int @@ -208,7 +251,7 @@ proc_pidpath(int pid, void * buffer, uint32_t buffersize) retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize); if (retval != -1) { - len = strlen(buffer); + len = (int)strlen(buffer); return(len); } return (0); @@ -293,6 +336,16 @@ proc_get_dirty(pid_t pid, uint32_t *flags) return 0; } +int +proc_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; +} + int proc_terminate(pid_t pid, int *sig) { @@ -312,11 +365,21 @@ proc_terminate(pid_t pid, int *sig) return 0; } +/* + * XXX the _fatal() variant both checks for an existing monitor + * (with important policy effects on first party background apps) + * and validates inputs. + */ int proc_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; @@ -337,7 +400,7 @@ proc_get_cpumon_params(pid_t pid, int *percentage, int *interval) if ((ret == 0) && (attr.ppattr_cpu_attr == PROC_POLICY_RSRCACT_NOTIFY_EXC)) { *percentage = attr.ppattr_cpu_percentage; - *interval = attr.ppattr_cpu_attr_interval; + *interval = (int)attr.ppattr_cpu_attr_interval; } else { *percentage = 0; *interval = 0; @@ -360,6 +423,16 @@ proc_set_cpumon_defaults(pid_t pid) PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0)); } +int +proc_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); +} + int proc_disable_cpumon(pid_t pid) { @@ -374,6 +447,60 @@ proc_disable_cpumon(pid_t pid) 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 + */ +int +proc_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); +} + int proc_set_wakemon_params(pid_t pid, int rate_hz, int flags __unused) { @@ -430,8 +557,20 @@ proc_disable_wakemon(pid_t pid) return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, ¶ms)); } +int +proc_list_uptrs(int pid, uint64_t *buf, uint32_t bufsz) +{ + return __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDLISTUPTRS, 0, + buf, bufsz); +} + +int +proc_list_dynkqueueids(int pid, kqueue_id_t *buf, uint32_t bufsz) +{ + return __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDLISTDYNKQUEUES, 0, + buf, bufsz); +} -#if TARGET_OS_EMBEDDED int proc_setcpu_percentage(pid_t pid, int action, int percentage) @@ -447,6 +586,17 @@ proc_setcpu_percentage(pid_t pid, int action, int percentage) return(errno); } +int +proc_clear_cpulimits(pid_t pid) +{ + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, (uint64_t)0) != -1) + return(0); + else + return(errno); +} + +#if TARGET_OS_EMBEDDED + int proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline) { @@ -462,7 +612,6 @@ proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline) } - int proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline) { @@ -478,17 +627,6 @@ proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint6 return(errno); } -int -proc_clear_cpulimits(pid_t pid) -{ - if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, (uint64_t)0) != -1) - return(0); - else - return(errno); - - -} - int proc_appstate(int pid, int * appstatep) { @@ -503,7 +641,6 @@ proc_appstate(int pid, int * appstatep) } - int proc_setappstate(int pid, int appstate) { @@ -565,6 +702,12 @@ proc_pidbind(int pid, uint64_t threadid, int bind) else return(errno); } + +int +proc_can_use_foreground_hw(int pid, uint32_t *reason) +{ + return __proc_info(PROC_INFO_CALL_CANUSEFGHW, pid, 0, NULL, reason, sizeof(*reason)); +} #endif /* TARGET_OS_EMBEDDED */ @@ -606,6 +749,7 @@ proc_importance_bad_assertion(char *reason) { 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 @@ -625,9 +769,12 @@ proc_importance_assertion_begin_with_msg(mach_msg_header_t *msg, if (assertion_token == NULL) return (EINVAL); - - /* Is this a boosting message? */ - if ((msg->msgh_bits & MACH_MSGH_BITS_RAISEIMP) != 0) { + +#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? @@ -640,21 +787,11 @@ proc_importance_assertion_begin_with_msg(mach_msg_header_t *msg, } /* Request an additional boost count */ - -#if TARGET_OS_EMBEDDED - rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, - PROC_POLICY_ACTION_ENABLE, - PROC_POLICY_APPTYPE, - PROC_POLICY_IOS_HOLDIMP, - NULL, getpid(), 0); -#else /* TARGET_OS_EMBEDDED */ rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_HOLD, PROC_POLICY_BOOST, PROC_POLICY_IMP_IMPORTANT, NULL, getpid(), 0); -#endif /* TARGET_OS_EMBEDDED */ - if (rval == 0) { *assertion_token = (uint64_t) &important_boost_assertion_token; return (0); @@ -683,21 +820,11 @@ proc_importance_assertion_complete(uint64_t assertion_token) return (0); if (assertion_token == (uint64_t) &important_boost_assertion_token) { - -#if TARGET_OS_EMBEDDED - rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, - PROC_POLICY_ACTION_ENABLE, - PROC_POLICY_APPTYPE, - PROC_POLICY_IOS_DROPIMP, - NULL, getpid(), 0); -#else /* TARGET_OS_EMBEDDED */ rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DROP, PROC_POLICY_BOOST, PROC_POLICY_IMP_IMPORTANT, - NULL, getpid(), 0); -#endif /* TARGET_OS_EMBEDDED */ - + NULL, getpid(), 0); if (rval == 0) { return (0); } else if (errno == EOVERFLOW) { @@ -712,6 +839,36 @@ proc_importance_assertion_complete(uint64_t assertion_token) } } +/* + * 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. + */ +int +proc_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. + */ +int +proc_denap_assertion_complete(uint64_t assertion_token) +{ + return proc_importance_assertion_complete(assertion_token); +} + #if !TARGET_OS_EMBEDDED int