2 * Copyright (c) 2006-2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <sys/cdefs.h>
30 #include <sys/errno.h>
31 #include <sys/msgbuf.h>
32 #include <sys/resource.h>
33 #include <sys/process_policy.h>
34 #include <sys/event.h>
35 #include <mach/message.h>
37 #include "libproc_internal.h"
39 int __proc_info(int callnum
, int pid
, int flavor
, uint64_t arg
, void * buffer
, int buffersize
);
40 int __proc_info_extended_id(int32_t callnum
, int32_t pid
, uint32_t flavor
, uint32_t flags
, uint64_t ext_id
, uint64_t arg
, user_addr_t buffer
, int32_t buffersize
);
41 __private_extern__
int proc_setthreadname(void * buffer
, int buffersize
);
42 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
);
43 int proc_rlimit_control(pid_t pid
, int flavor
, void *arg
);
46 proc_listpids(uint32_t type
, uint32_t typeinfo
, void *buffer
, int buffersize
)
50 if ((type
>= PROC_ALL_PIDS
) || (type
<= PROC_PPID_ONLY
)) {
51 if ((retval
= __proc_info(PROC_INFO_CALL_LISTPIDS
, type
, typeinfo
, (uint64_t)0, buffer
, buffersize
)) == -1) {
63 proc_listallpids(void * buffer
, int buffersize
)
66 numpids
= proc_listpids(PROC_ALL_PIDS
, (uint32_t)0, buffer
, buffersize
);
71 return numpids
/ sizeof(int);
76 proc_listpgrppids(pid_t pgrpid
, void * buffer
, int buffersize
)
79 numpids
= proc_listpids(PROC_PGRP_ONLY
, (uint32_t)pgrpid
, buffer
, buffersize
);
83 return numpids
/ sizeof(int);
88 proc_listchildpids(pid_t ppid
, void * buffer
, int buffersize
)
91 numpids
= proc_listpids(PROC_PPID_ONLY
, (uint32_t)ppid
, buffer
, buffersize
);
95 return numpids
/ sizeof(int);
101 proc_pidinfo(int pid
, int flavor
, uint64_t arg
, void *buffer
, int buffersize
)
105 if ((retval
= __proc_info(PROC_INFO_CALL_PIDINFO
, pid
, flavor
, arg
, buffer
, buffersize
)) == -1) {
114 proc_pidoriginatorinfo(int flavor
, void *buffer
, int buffersize
)
118 if ((retval
= __proc_info(PROC_INFO_CALL_PIDORIGINATORINFO
, getpid(), flavor
, 0, buffer
, buffersize
)) == -1) {
126 proc_listcoalitions(int flavor
, int coaltype
, void *buffer
, int buffersize
)
130 if ((retval
= __proc_info(PROC_INFO_CALL_LISTCOALITIONS
, flavor
, coaltype
, 0, buffer
, buffersize
)) == -1) {
138 proc_pid_rusage(int pid
, int flavor
, rusage_info_t
*buffer
)
140 return __proc_info(PROC_INFO_CALL_PIDRUSAGE
, pid
, flavor
, 0, buffer
, 0);
144 proc_setthread_cpupercent(uint8_t percentage
, uint32_t ms_refill
)
148 /* Pack percentage and refill into a 32-bit number to match existing kernel implementation */
149 if ((percentage
>= 100) || (ms_refill
& ~0xffffffU
)) {
154 arg
= ((ms_refill
<< 8) | percentage
);
156 return proc_rlimit_control(-1, RLIMIT_THREAD_CPULIMITS
, (void *)(uintptr_t)arg
);
160 proc_pidfdinfo(int pid
, int fd
, int flavor
, void * buffer
, int buffersize
)
164 if ((retval
= __proc_info(PROC_INFO_CALL_PIDFDINFO
, pid
, flavor
, (uint64_t)fd
, buffer
, buffersize
)) == -1) {
173 proc_pidfileportinfo(int pid
, uint32_t fileport
, int flavor
, void *buffer
, int buffersize
)
177 if ((retval
= __proc_info(PROC_INFO_CALL_PIDFILEPORTINFO
, pid
, flavor
, (uint64_t)fileport
, buffer
, buffersize
)) == -1) {
184 proc_piddynkqueueinfo(int pid
, int flavor
, kqueue_id_t kq_id
, void *buffer
, int buffersize
)
188 if ((ret
= __proc_info(PROC_INFO_CALL_PIDDYNKQUEUEINFO
, pid
, flavor
, (uint64_t)kq_id
, buffer
, buffersize
)) == -1) {
196 proc_udata_info(int pid
, int flavor
, void *buffer
, int buffersize
)
198 return __proc_info(PROC_INFO_CALL_UDATA_INFO
, pid
, flavor
, 0, buffer
, buffersize
);
202 proc_name(int pid
, void * buffer
, uint32_t buffersize
)
205 struct proc_bsdinfo pbsd
;
208 if (buffersize
< sizeof(pbsd
.pbi_name
)) {
213 retval
= proc_pidinfo(pid
, PROC_PIDTBSDINFO
, (uint64_t)0, &pbsd
, sizeof(struct proc_bsdinfo
));
215 if (pbsd
.pbi_name
[0]) {
216 bcopy(&pbsd
.pbi_name
, buffer
, sizeof(pbsd
.pbi_name
));
218 bcopy(&pbsd
.pbi_comm
, buffer
, sizeof(pbsd
.pbi_comm
));
220 len
= (int)strlen(buffer
);
227 proc_regionfilename(int pid
, uint64_t address
, void * buffer
, uint32_t buffersize
)
230 struct proc_regionpath path
;
232 if (buffersize
< MAXPATHLEN
) {
237 retval
= proc_pidinfo(pid
, PROC_PIDREGIONPATH
, (uint64_t)address
, &path
, sizeof(struct proc_regionpath
));
239 return (int)(strlcpy(buffer
, path
.prpo_path
, buffersize
));
245 proc_kmsgbuf(void * buffer
, uint32_t buffersize
)
249 if ((retval
= __proc_info(PROC_INFO_CALL_KERNMSGBUF
, 0, 0, (uint64_t)0, buffer
, buffersize
)) == -1) {
256 proc_pidpath(int pid
, void * buffer
, uint32_t buffersize
)
260 if (buffersize
< PROC_PIDPATHINFO_SIZE
) {
264 if (buffersize
> PROC_PIDPATHINFO_MAXSIZE
) {
269 retval
= __proc_info(PROC_INFO_CALL_PIDINFO
, pid
, PROC_PIDPATHINFO
, (uint64_t)0, buffer
, buffersize
);
271 len
= (int)strlen(buffer
);
278 proc_pidpath_audittoken(audit_token_t
*audittoken
, void * buffer
, uint32_t buffersize
)
282 if (buffersize
< PROC_PIDPATHINFO_SIZE
) {
286 if (buffersize
> PROC_PIDPATHINFO_MAXSIZE
) {
291 int pid
= audittoken
->val
[5];
292 int idversion
= audittoken
->val
[7];
294 retval
= __proc_info_extended_id(PROC_INFO_CALL_PIDINFO
, pid
, PROC_PIDPATHINFO
, PIF_COMPARE_IDVERSION
, (uint64_t)idversion
,
295 (uint64_t)0, buffer
, buffersize
);
297 len
= (int)strlen(buffer
);
304 proc_libversion(int *major
, int * minor
)
316 proc_setpcontrol(const int control
)
320 if (control
< PROC_SETPC_NONE
|| control
> PROC_SETPC_TERMINATE
) {
324 if ((retval
= __proc_info(PROC_INFO_CALL_SETCONTROL
, getpid(), PROC_SELFSET_PCONTROL
, (uint64_t)control
, NULL
, 0)) == -1) {
332 __private_extern__
int
333 proc_setthreadname(void * buffer
, int buffersize
)
337 retval
= __proc_info(PROC_INFO_CALL_SETCONTROL
, getpid(), PROC_SELFSET_THREADNAME
, (uint64_t)0, buffer
, buffersize
);
347 proc_track_dirty(pid_t pid
, uint32_t flags
)
349 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL
, pid
, PROC_DIRTYCONTROL_TRACK
, flags
, NULL
, 0) == -1) {
357 proc_set_dirty(pid_t pid
, bool dirty
)
359 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL
, pid
, PROC_DIRTYCONTROL_SET
, dirty
, NULL
, 0) == -1) {
367 proc_get_dirty(pid_t pid
, uint32_t *flags
)
375 retval
= __proc_info(PROC_INFO_CALL_DIRTYCONTROL
, pid
, PROC_DIRTYCONTROL_GET
, 0, NULL
, 0);
386 proc_clear_dirty(pid_t pid
, uint32_t flags
)
388 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL
, pid
, PROC_DIRTYCONTROL_CLEAR
, flags
, NULL
, 0) == -1) {
396 proc_terminate(pid_t pid
, int *sig
)
404 retval
= __proc_info(PROC_INFO_CALL_TERMINATE
, pid
, 0, 0, NULL
, 0);
415 * XXX the _fatal() variant both checks for an existing monitor
416 * (with important policy effects on first party background apps)
417 * and validates inputs.
420 proc_set_cpumon_params(pid_t pid
, int percentage
, int interval
)
422 proc_policy_cpuusage_attr_t attr
;
424 /* no argument validation ...
425 * task_set_cpuusage() ignores 0 values and squashes negative
426 * values into uint32_t.
429 attr
.ppattr_cpu_attr
= PROC_POLICY_RSRCACT_NOTIFY_EXC
;
430 attr
.ppattr_cpu_percentage
= percentage
;
431 attr
.ppattr_cpu_attr_interval
= (uint64_t)interval
;
432 attr
.ppattr_cpu_attr_deadline
= 0;
434 return __process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_SET
, PROC_POLICY_RESOURCE_USAGE
,
435 PROC_POLICY_RUSAGE_CPU
, (proc_policy_attribute_t
*)&attr
, pid
, 0);
439 proc_get_cpumon_params(pid_t pid
, int *percentage
, int *interval
)
441 proc_policy_cpuusage_attr_t attr
;
444 ret
= __process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_GET
, PROC_POLICY_RESOURCE_USAGE
,
445 PROC_POLICY_RUSAGE_CPU
, (proc_policy_attribute_t
*)&attr
, pid
, 0);
447 if ((ret
== 0) && (attr
.ppattr_cpu_attr
== PROC_POLICY_RSRCACT_NOTIFY_EXC
)) {
448 *percentage
= attr
.ppattr_cpu_percentage
;
449 *interval
= (int)attr
.ppattr_cpu_attr_interval
;
459 proc_set_cpumon_defaults(pid_t pid
)
461 proc_policy_cpuusage_attr_t attr
;
463 attr
.ppattr_cpu_attr
= PROC_POLICY_RSRCACT_NOTIFY_EXC
;
464 attr
.ppattr_cpu_percentage
= PROC_POLICY_CPUMON_DEFAULTS
;
465 attr
.ppattr_cpu_attr_interval
= 0;
466 attr
.ppattr_cpu_attr_deadline
= 0;
468 return __process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_SET
, PROC_POLICY_RESOURCE_USAGE
,
469 PROC_POLICY_RUSAGE_CPU
, (proc_policy_attribute_t
*)&attr
, pid
, 0);
473 proc_resume_cpumon(pid_t pid
)
475 return __process_policy(PROC_POLICY_SCOPE_PROCESS
,
476 PROC_POLICY_ACTION_ENABLE
,
477 PROC_POLICY_RESOURCE_USAGE
,
478 PROC_POLICY_RUSAGE_CPU
,
483 proc_disable_cpumon(pid_t pid
)
485 proc_policy_cpuusage_attr_t attr
;
487 attr
.ppattr_cpu_attr
= PROC_POLICY_RSRCACT_NOTIFY_EXC
;
488 attr
.ppattr_cpu_percentage
= PROC_POLICY_CPUMON_DISABLE
;
489 attr
.ppattr_cpu_attr_interval
= 0;
490 attr
.ppattr_cpu_attr_deadline
= 0;
492 return __process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_SET
, PROC_POLICY_RESOURCE_USAGE
,
493 PROC_POLICY_RUSAGE_CPU
, (proc_policy_attribute_t
*)&attr
, pid
, 0);
498 * Turn on the CPU usage monitor using the supplied parameters, and make
499 * violations of the monitor fatal.
501 * Returns: 0 on success;
502 * -1 on failure and sets errno
505 proc_set_cpumon_params_fatal(pid_t pid
, int percentage
, int interval
)
507 int current_percentage
= 0;
508 int current_interval
= 0; /* intervals are in seconds */
511 if ((percentage
<= 0) || (interval
<= 0)) {
517 * Do a simple query to see if CPU monitoring is
518 * already active. If either the percentage or the
519 * interval is nonzero, then CPU monitoring is
520 * already in use for this process.
522 * XXX: need set...() and set..fatal() to behave similarly.
523 * Currently, this check prevents 1st party apps (which get a
524 * default non-fatal monitor) not to get a fatal monitor.
526 (void)proc_get_cpumon_params(pid
, ¤t_percentage
, ¤t_interval
);
527 if (current_percentage
|| current_interval
) {
529 * The CPU monitor appears to be active.
530 * We choose not to disturb those settings.
536 if ((ret
= proc_set_cpumon_params(pid
, percentage
, interval
)) != 0) {
537 /* Failed to activate the CPU monitor */
541 if ((ret
= proc_rlimit_control(pid
, RLIMIT_CPU_USAGE_MONITOR
, (void *)(uintptr_t)CPUMON_MAKE_FATAL
)) != 0) {
542 /* Failed to set termination, back out the CPU monitor settings. */
543 (void)proc_disable_cpumon(pid
);
550 proc_set_wakemon_params(pid_t pid
, int rate_hz
, int flags __unused
)
552 struct proc_rlimit_control_wakeupmon params
;
554 params
.wm_flags
= WAKEMON_ENABLE
;
555 params
.wm_rate
= rate_hz
;
557 return proc_rlimit_control(pid
, RLIMIT_WAKEUPS_MONITOR
, ¶ms
);
560 #ifndef WAKEMON_GET_PARAMS
561 #define WAKEMON_GET_PARAMS 0x4
562 #define WAKEMON_SET_DEFAULTS 0x8
566 proc_get_wakemon_params(pid_t pid
, int *rate_hz
, int *flags
)
568 struct proc_rlimit_control_wakeupmon params
;
571 params
.wm_flags
= WAKEMON_GET_PARAMS
;
573 if ((error
= proc_rlimit_control(pid
, RLIMIT_WAKEUPS_MONITOR
, ¶ms
)) != 0) {
577 *rate_hz
= params
.wm_rate
;
578 *flags
= params
.wm_flags
;
584 proc_set_wakemon_defaults(pid_t pid
)
586 struct proc_rlimit_control_wakeupmon params
;
588 params
.wm_flags
= WAKEMON_ENABLE
| WAKEMON_SET_DEFAULTS
;
591 return proc_rlimit_control(pid
, RLIMIT_WAKEUPS_MONITOR
, ¶ms
);
595 proc_disable_wakemon(pid_t pid
)
597 struct proc_rlimit_control_wakeupmon params
;
599 params
.wm_flags
= WAKEMON_DISABLE
;
602 return proc_rlimit_control(pid
, RLIMIT_WAKEUPS_MONITOR
, ¶ms
);
606 proc_list_uptrs(int pid
, uint64_t *buf
, uint32_t bufsz
)
608 return __proc_info(PROC_INFO_CALL_PIDINFO
, pid
, PROC_PIDLISTUPTRS
, 0,
613 proc_list_dynkqueueids(int pid
, kqueue_id_t
*buf
, uint32_t bufsz
)
615 return __proc_info(PROC_INFO_CALL_PIDINFO
, pid
, PROC_PIDLISTDYNKQUEUES
, 0,
621 proc_setcpu_percentage(pid_t pid
, int action
, int percentage
)
623 proc_policy_cpuusage_attr_t attr
;
625 bzero(&attr
, sizeof(proc_policy_cpuusage_attr_t
));
626 attr
.ppattr_cpu_attr
= action
;
627 attr
.ppattr_cpu_percentage
= percentage
;
628 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) {
636 proc_reset_footprint_interval(pid_t pid
)
638 return proc_rlimit_control(pid
, RLIMIT_FOOTPRINT_INTERVAL
, (void *)(uintptr_t)FOOTPRINT_INTERVAL_RESET
);
642 proc_clear_cpulimits(pid_t pid
)
644 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) {
651 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
654 proc_setcpu_deadline(pid_t pid
, int action
, uint64_t deadline
)
656 proc_policy_cpuusage_attr_t attr
;
658 bzero(&attr
, sizeof(proc_policy_cpuusage_attr_t
));
659 attr
.ppattr_cpu_attr
= action
;
660 attr
.ppattr_cpu_attr_deadline
= deadline
;
661 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) {
669 proc_setcpu_percentage_withdeadline(pid_t pid
, int action
, int percentage
, uint64_t deadline
)
671 proc_policy_cpuusage_attr_t attr
;
673 bzero(&attr
, sizeof(proc_policy_cpuusage_attr_t
));
674 attr
.ppattr_cpu_attr
= action
;
675 attr
.ppattr_cpu_percentage
= percentage
;
676 attr
.ppattr_cpu_attr_deadline
= deadline
;
677 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) {
685 proc_appstate(int pid
, int * appstatep
)
689 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) {
690 if (appstatep
!= NULL
) {
700 proc_setappstate(int pid
, int appstate
)
702 int state
= appstate
;
705 case PROC_APPSTATE_NONE
:
706 case PROC_APPSTATE_ACTIVE
:
707 case PROC_APPSTATE_INACTIVE
:
708 case PROC_APPSTATE_BACKGROUND
:
709 case PROC_APPSTATE_NONUI
:
714 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) {
722 proc_devstatusnotify(int devicestatus
)
724 int state
= devicestatus
;
726 switch (devicestatus
) {
727 case PROC_DEVSTATUS_SHORTTERM
:
728 case PROC_DEVSTATUS_LONGTERM
:
734 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) {
742 proc_pidbind(int pid
, uint64_t threadid
, int bind
)
748 case PROC_PIDBIND_CLEAR
:
749 passpid
= getpid(); /* ignore pid on clear */
751 case PROC_PIDBIND_SET
:
756 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) {
764 proc_can_use_foreground_hw(int pid
, uint32_t *reason
)
766 return __proc_info(PROC_INFO_CALL_CANUSEFGHW
, pid
, 0, 0, reason
, sizeof(*reason
));
768 #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
771 /* Donate importance to adaptive processes from this process */
773 proc_donate_importance_boost()
777 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
778 rval
= __process_policy(PROC_POLICY_SCOPE_PROCESS
,
779 PROC_POLICY_ACTION_ENABLE
,
781 PROC_POLICY_IOS_DONATEIMP
,
782 NULL
, getpid(), (uint64_t)0);
783 #else /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
784 rval
= __process_policy(PROC_POLICY_SCOPE_PROCESS
,
785 PROC_POLICY_ACTION_SET
,
787 PROC_POLICY_IMP_DONATION
,
789 #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
798 static __attribute__((noinline
)) void
799 proc_importance_bad_assertion(char *reason
)
805 * Use the address of these variables as the token. This way, they can be
806 * printed in the debugger as useful names.
808 uint64_t important_boost_assertion_token
= 0xfafafafafafafafa;
809 uint64_t normal_boost_assertion_token
= 0xfbfbfbfbfbfbfbfb;
810 uint64_t non_boost_assertion_token
= 0xfcfcfcfcfcfcfcfc;
811 uint64_t denap_boost_assertion_token
= 0xfdfdfdfdfdfdfdfd;
814 * Accept the boost on a message, or request another boost assertion
815 * if we have already accepted the implicit boost for this message.
817 * Returns EOVERFLOW if an attempt is made to take an extra assertion when not boosted.
819 * Returns EIO if the message was not a boosting message.
820 * TODO: Return a 'non-boost' token instead.
823 proc_importance_assertion_begin_with_msg(mach_msg_header_t
*msg
,
824 __unused mach_msg_trailer_t
*trailer
,
825 uint64_t *assertion_token
)
829 if (assertion_token
== NULL
) {
833 #define LEGACYBOOSTMASK (MACH_MSGH_BITS_VOUCHER_MASK | MACH_MSGH_BITS_RAISEIMP)
834 #define LEGACYBOOSTED(m) (((m)->msgh_bits & LEGACYBOOSTMASK) == MACH_MSGH_BITS_RAISEIMP)
836 /* Is this a legacy boosted message? */
837 if (LEGACYBOOSTED(msg
)) {
839 * Have we accepted the implicit boost for this message yet?
840 * If we haven't accepted it yet, no need to call into kernel.
842 if ((msg
->msgh_bits
& MACH_MSGH_BITS_IMPHOLDASRT
) == 0) {
843 msg
->msgh_bits
|= MACH_MSGH_BITS_IMPHOLDASRT
;
844 *assertion_token
= (uint64_t) &important_boost_assertion_token
;
848 /* Request an additional boost count */
849 rval
= __process_policy(PROC_POLICY_SCOPE_PROCESS
,
850 PROC_POLICY_ACTION_HOLD
,
852 PROC_POLICY_IMP_IMPORTANT
,
855 *assertion_token
= (uint64_t) &important_boost_assertion_token
;
857 } else if (errno
== EOVERFLOW
) {
858 proc_importance_bad_assertion("Attempted to take assertion while not boosted");
870 * Drop a boost assertion.
871 * Returns EOVERFLOW on boost assertion underflow.
874 proc_importance_assertion_complete(uint64_t assertion_token
)
878 if (assertion_token
== 0) {
882 if (assertion_token
== (uint64_t) &important_boost_assertion_token
) {
883 rval
= __process_policy(PROC_POLICY_SCOPE_PROCESS
,
884 PROC_POLICY_ACTION_DROP
,
886 PROC_POLICY_IMP_IMPORTANT
,
890 } else if (errno
== EOVERFLOW
) {
891 proc_importance_bad_assertion("Attempted to drop too many assertions");
897 proc_importance_bad_assertion("Attempted to drop assertion with invalid token");
903 * Accept the De-Nap boost on a message, or request another boost assertion
904 * if we have already accepted the implicit boost for this message.
906 * Interface is deprecated before it really got started - just as synonym
907 * for proc_importance_assertion_begin_with_msg() now.
910 proc_denap_assertion_begin_with_msg(mach_msg_header_t
*msg
,
911 uint64_t *assertion_token
)
913 #pragma clang diagnostic push
914 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
915 return proc_importance_assertion_begin_with_msg(msg
, NULL
, assertion_token
);
916 #pragma clang diagnostic pop
921 * Drop a denap boost assertion.
923 * Interface is deprecated before it really got started - just a synonym
924 * for proc_importance_assertion_complete() now.
927 proc_denap_assertion_complete(uint64_t assertion_token
)
929 return proc_importance_assertion_complete(assertion_token
);
932 #if !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
935 proc_clear_vmpressure(pid_t pid
)
937 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) {
944 /* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */
946 proc_set_owner_vmpressure(void)
950 if ((retval
= __proc_info(PROC_INFO_CALL_SETCONTROL
, getpid(), PROC_SELFSET_VMRSRCOWNER
, (uint64_t)0, NULL
, 0)) == -1) {
957 /* mark yourself to delay idle sleep on disk IO */
959 proc_set_delayidlesleep(void)
963 if ((retval
= __proc_info(PROC_INFO_CALL_SETCONTROL
, getpid(), PROC_SELFSET_DELAYIDLESLEEP
, (uint64_t)1, NULL
, 0)) == -1) {
970 /* Reset yourself to delay idle sleep on disk IO, if already set */
972 proc_clear_delayidlesleep(void)
976 if ((retval
= __proc_info(PROC_INFO_CALL_SETCONTROL
, getpid(), PROC_SELFSET_DELAYIDLESLEEP
, (uint64_t)0, NULL
, 0)) == -1) {
983 /* disable the launch time backgroudn policy and restore the process to default group */
985 proc_disable_apptype(pid_t pid
, int apptype
)
988 case PROC_POLICY_OSX_APPTYPE_TAL
:
989 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT
:
995 if (__process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_DISABLE
, PROC_POLICY_APPTYPE
, apptype
, NULL
, pid
, (uint64_t)0) != -1) {
1002 /* re-enable the launch time background policy if it had been disabled. */
1004 proc_enable_apptype(pid_t pid
, int apptype
)
1007 case PROC_POLICY_OSX_APPTYPE_TAL
:
1008 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT
:
1014 if (__process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_ENABLE
, PROC_POLICY_APPTYPE
, apptype
, NULL
, pid
, (uint64_t)0) != -1) {
1021 #if !TARGET_OS_SIMULATOR
1024 proc_suppress(__unused pid_t pid
, __unused
uint64_t *generation
)
1029 #endif /* !TARGET_OS_SIMULATOR */
1031 #endif /* !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
1034 proc_set_no_smt(void)
1036 if (__process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_APPLY
, PROC_POLICY_NO_SMT
, 0, NULL
, getpid(), (uint64_t)0) == -1) {
1043 proc_setthread_no_smt(void)
1045 extern uint64_t __thread_selfid(void);
1046 if (__process_policy(PROC_POLICY_SCOPE_THREAD
, PROC_POLICY_ACTION_APPLY
, PROC_POLICY_NO_SMT
, 0, NULL
, 0, __thread_selfid()) == -1) {
1053 proc_set_csm(uint32_t flags
)
1055 const uint32_t mask
= PROC_CSM_ALL
| PROC_CSM_TECS
| PROC_CSM_NOSMT
;
1056 if ((flags
& ~mask
) != 0) {
1060 if (flags
& (PROC_CSM_NOSMT
| PROC_CSM_ALL
)) {
1061 if (__process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_APPLY
, PROC_POLICY_NO_SMT
, 0, NULL
, getpid(), (uint64_t)0) == -1) {
1066 if (flags
& (PROC_CSM_TECS
| PROC_CSM_ALL
)) {
1067 if (__process_policy(PROC_POLICY_SCOPE_PROCESS
, PROC_POLICY_ACTION_APPLY
, PROC_POLICY_TECS
, 0, NULL
, getpid(), (uint64_t)0) == -1) {
1076 proc_setthread_csm(uint32_t flags
)
1078 extern uint64_t __thread_selfid(void);
1079 const uint32_t mask
= PROC_CSM_ALL
| PROC_CSM_TECS
| PROC_CSM_NOSMT
;
1080 if ((flags
& ~mask
) != 0) {
1084 if (flags
& (PROC_CSM_NOSMT
| PROC_CSM_ALL
)) {
1085 if (__process_policy(PROC_POLICY_SCOPE_THREAD
, PROC_POLICY_ACTION_APPLY
, PROC_POLICY_NO_SMT
, 0, NULL
, 0, __thread_selfid()) == -1) {
1090 if (flags
& (PROC_CSM_TECS
| PROC_CSM_ALL
)) {
1091 if (__process_policy(PROC_POLICY_SCOPE_THREAD
, PROC_POLICY_ACTION_APPLY
, PROC_POLICY_TECS
, 0, NULL
, 0, __thread_selfid()) == -1) {