X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3e170ce000f1506b7b5d2c5c7faec85ceabb573d..5c9f46613a83ebfc29a5b1f099448259e96a98f0:/libsyscall/wrappers/libproc/libproc.c diff --git a/libsyscall/wrappers/libproc/libproc.c b/libsyscall/wrappers/libproc/libproc.c index 730a15e41..255664d9c 100644 --- a/libsyscall/wrappers/libproc/libproc.c +++ b/libsyscall/wrappers/libproc/libproc.c @@ -170,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) @@ -199,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) { @@ -209,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 = (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 ((int)(strlcpy(buffer, reginfo.prp_vip.vip_path, MAXPATHLEN))); } - return(0); - + return(0); } int @@ -362,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; @@ -410,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) { @@ -449,6 +472,10 @@ proc_set_cpumon_params_fatal(pid_t pid, int percentage, int interval) * 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) @@ -533,76 +560,155 @@ proc_disable_wakemon(pid_t pid) int proc_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 */ + return __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDLISTUPTRS, 0, + buf, bufsz); +} - /* if buffer is empty, this call simply counts the knotes */ - if (bufsz > 0 && buf == NULL) { - errno = EFAULT; - return -1; - } +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); +} - struct proc_fdinfo fdlist[OPEN_MAX]; - nfds = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdlist, OPEN_MAX*sizeof(struct proc_fdinfo)); - if (nfds <= 0 || nfds > OPEN_MAX) { - return -1; - } - struct kevent_extinfo *kqext = malloc(knote_max * sizeof(struct kevent_extinfo)); - if (!kqext) { - errno = ENOMEM; - return -1; - } +int +proc_setcpu_percentage(pid_t pid, int action, int percentage) +{ + proc_policy_cpuusage_attr_t attr; - for (i = 0; i < nfds; i++) { - if (fdlist[i].proc_fdtype != PROX_FDTYPE_KQUEUE) { - continue; - } + bzero(&attr, sizeof(proc_policy_cpuusage_attr_t)); + attr.ppattr_cpu_attr = action; + attr.ppattr_cpu_percentage = percentage; + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, (uint64_t)0) != -1) + return(0); + else + return(errno); +} - 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; - } +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 (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; - } +#if TARGET_OS_EMBEDDED + +int +proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline) +{ + proc_policy_cpuusage_attr_t attr; - for (j = 0; j < nkns; j++) { - if (kqext[j].kqext_kev.udata == 0) { - continue; - } + bzero(&attr, sizeof(proc_policy_cpuusage_attr_t)); + attr.ppattr_cpu_attr = action; + attr.ppattr_cpu_attr_deadline = deadline; + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, (uint64_t)0) != -1) + return(0); + else + return(errno); - if (bufsz >= sizeof(uint64_t)) { - *buf++ = kqext[j].kqext_kev.udata; - bufsz -= sizeof(uint64_t); - } - count++; - } +} + +int +proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline) +{ + proc_policy_cpuusage_attr_t attr; + + bzero(&attr, sizeof(proc_policy_cpuusage_attr_t)); + attr.ppattr_cpu_attr = action; + attr.ppattr_cpu_percentage = percentage; + attr.ppattr_cpu_attr_deadline = deadline; + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, (uint64_t)0) != -1) + return(0); + else + return(errno); +} + +int +proc_appstate(int pid, int * appstatep) +{ + int state; + + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (proc_policy_attribute_t*)&state, pid, (uint64_t)0) != -1) { + if (appstatep != NULL) + *appstatep = state; + return(0); + } else + return(errno); + +} + +int +proc_setappstate(int pid, int appstate) +{ + int state = appstate; + + switch (state) { + case PROC_APPSTATE_NONE: + case PROC_APPSTATE_ACTIVE: + case PROC_APPSTATE_INACTIVE: + case PROC_APPSTATE_BACKGROUND: + case PROC_APPSTATE_NONUI: + break; + default: + return(EINVAL); } + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (proc_policy_attribute_t*)&state, pid, (uint64_t)0) != -1) + return(0); + else + return(errno); +} - free(kqext); - return count; +int +proc_devstatusnotify(int devicestatus) +{ + int state = devicestatus; + + switch (devicestatus) { + case PROC_DEVSTATUS_SHORTTERM: + case PROC_DEVSTATUS_LONGTERM: + break; + default: + return(EINVAL); + } + + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_DEVSTATUS, (proc_policy_attribute_t*)&state, getpid(), (uint64_t)0) != -1) { + return(0); + } else + return(errno); + +} + +int +proc_pidbind(int pid, uint64_t threadid, int bind) +{ + int state = bind; + pid_t passpid = pid; + + switch (bind) { + case PROC_PIDBIND_CLEAR: + passpid = getpid(); /* ignore pid on clear */ + break; + case PROC_PIDBIND_SET: + break; + default: + return(EINVAL); + } + if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_PIDBIND, (proc_policy_attribute_t*)&state, passpid, threadid) != -1) + return(0); + 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 */ /* Donate importance to adaptive processes from this process */ @@ -611,11 +717,19 @@ proc_donate_importance_boost() { int rval; +#if TARGET_OS_EMBEDDED + rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, + PROC_POLICY_ACTION_ENABLE, + PROC_POLICY_APPTYPE, + PROC_POLICY_IOS_DONATEIMP, + NULL, getpid(), (uint64_t)0); +#else /* TARGET_OS_EMBEDDED */ rval = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_BOOST, PROC_POLICY_IMP_DONATION, NULL, getpid(), 0); +#endif /* TARGET_OS_EMBEDDED */ if (rval == 0) return (0); @@ -755,6 +869,7 @@ proc_denap_assertion_complete(uint64_t assertion_token) return proc_importance_assertion_complete(assertion_token); } +#if !TARGET_OS_EMBEDDED int proc_clear_vmpressure(pid_t pid) @@ -850,6 +965,7 @@ proc_suppress(__unused pid_t pid, __unused uint64_t *generation) #endif /* !TARGET_IPHONE_SIMULATOR */ +#endif /* !TARGET_OS_EMBEDDED */