1/*
2 * Copyright (c) 2006, 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <sys/cdefs.h>
25#include <unistd.h>
26#include <errno.h>
27#include <string.h>
28#include <strings.h>
29#include <sys/errno.h>
30#include <sys/msgbuf.h>
31#include <sys/resource.h>
32#define BUILD_LIBSYSCALL 1
33#include <sys/process_policy.h>
34#include <mach/message.h>
35
36#include "libproc_internal.h"
37
38int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
39__private_extern__ int proc_setthreadname(void * buffer, int buffersize);
40int __process_policy(int scope, int action, int policy, int policy_subtype, proc_policy_attribute_t * attrp, pid_t target_pid, uint64_t target_threadid);
41int proc_rlimit_control(pid_t pid, int flavor, void *arg);
42
43int
44proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize)
45{
46	int retval;
47
48	if ((type >= PROC_ALL_PIDS) || (type <= PROC_PPID_ONLY)) {
49		if ((retval = __proc_info(PROC_INFO_CALL_LISTPIDS, type, typeinfo,(uint64_t)0, buffer, buffersize)) == -1)
50			return(0);
51	} else {
52		errno = EINVAL;
53		retval = 0;
54	}
55	return(retval);
56}
57
58
59int
60proc_listallpids(void * buffer, int buffersize)
61{
62	int numpids;
63	numpids = proc_listpids(PROC_ALL_PIDS, (uint32_t)0, buffer, buffersize);
64
65	if (numpids == -1)
66		return(-1);
67	else
68		return(numpids/sizeof(int));
69}
70
71int
72proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize)
73{
74	int numpids;
75	numpids = proc_listpids(PROC_PGRP_ONLY, (uint32_t)pgrpid, buffer, buffersize);
76	if (numpids == -1)
77		return(-1);
78	else
79		return(numpids/sizeof(int));
80}
81
82int
83proc_listchildpids(pid_t ppid, void * buffer, int buffersize)
84{
85	int numpids;
86	numpids = proc_listpids(PROC_PPID_ONLY, (uint32_t)ppid, buffer, buffersize);
87	if (numpids == -1)
88		return(-1);
89	else
90		return(numpids/sizeof(int));
91}
92
93
94int
95proc_pidinfo(int pid, int flavor, uint64_t arg,  void *buffer, int buffersize)
96{
97	int retval;
98
99	if ((retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor,  arg,  buffer, buffersize)) == -1)
100		return(0);
101
102	return(retval);
103}
104
105int
106proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer)
107{
108	return (__proc_info(PROC_INFO_CALL_PIDRUSAGE, pid, flavor, 0, buffer, 0));
109}
110
111int
112proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)
113{
114	int retval;
115
116	if ((retval = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid,  flavor, (uint64_t)fd, buffer, buffersize)) == -1)
117		return(0);
118
119	return (retval);
120}
121
122
123int
124proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize)
125{
126	int retval;
127
128	if ((retval = __proc_info(PROC_INFO_CALL_PIDFILEPORTINFO, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1)
129		return (0);
130	return (retval);
131}
132
133
134int
135proc_name(int pid, void * buffer, uint32_t buffersize)
136{
137	int retval = 0, len;
138	struct proc_bsdinfo pbsd;
139
140
141	if (buffersize < sizeof(pbsd.pbi_name)) {
142		errno = ENOMEM;
143		return(0);
144	}
145
146	retval = proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &pbsd, sizeof(struct proc_bsdinfo));
147	if (retval != 0) {
148		if (pbsd.pbi_name[0]) {
149			bcopy(&pbsd.pbi_name, buffer, sizeof(pbsd.pbi_name));
150		} else {
151			bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm));
152		}
153		len = strlen(buffer);
154		return(len);
155	}
156	return(0);
157}
158
159int
160proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)
161{
162	int retval = 0, len;
163	struct proc_regionwithpathinfo reginfo;
164
165	if (buffersize < MAXPATHLEN) {
166		errno = ENOMEM;
167		return(0);
168	}
169
170	retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, &reginfo, sizeof(struct proc_regionwithpathinfo));
171	if (retval != -1) {
172		len = strlen(&reginfo.prp_vip.vip_path[0]);
173		if (len != 0) {
174			if (len > MAXPATHLEN)
175				len = MAXPATHLEN;
176			bcopy(&reginfo.prp_vip.vip_path[0], buffer, len);
177			return(len);
178		}
179		return(0);
180	}
181	return(0);
182
183}
184
185int
186proc_kmsgbuf(void * buffer, uint32_t  buffersize)
187{
188	int retval;
189
190	if ((retval = __proc_info(PROC_INFO_CALL_KERNMSGBUF, 0,  0, (uint64_t)0, buffer, buffersize)) == -1)
191		return(0);
192	return (retval);
193}
194
195int
196proc_pidpath(int pid, void * buffer, uint32_t  buffersize)
197{
198	int retval, len;
199
200	if (buffersize < PROC_PIDPATHINFO_SIZE) {
201		errno = ENOMEM;
202		return(0);
203	}
204	if (buffersize >  PROC_PIDPATHINFO_MAXSIZE) {
205		errno = EOVERFLOW;
206		return(0);
207	}
208
209	retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO,  (uint64_t)0,  buffer, buffersize);
210	if (retval != -1) {
211		len = strlen(buffer);
212		return(len);
213	}
214	return (0);
215}
216
217
218int
219proc_libversion(int *major, int * minor)
220{
221
222	if (major != NULL)
223		*major = 1;
224	if (minor != NULL)
225		*minor = 1;
226	return(0);
227}
228
229int
230proc_setpcontrol(const int control)
231{
232	int retval ;
233
234	if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE)
235		return(EINVAL);
236
237	if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1)
238		return(errno);
239
240	return(0);
241}
242
243
244__private_extern__ int
245proc_setthreadname(void * buffer, int buffersize)
246{
247	int retval;
248
249        retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize);
250
251	if (retval == -1)
252                return(errno);
253	else
254		return(0);
255}
256
257int
258proc_track_dirty(pid_t pid, uint32_t flags)
259{
260	if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_TRACK, flags, NULL, 0) == -1) {
261		return errno;
262	}
263
264	return 0;
265}
266
267int
268proc_set_dirty(pid_t pid, bool dirty)
269{
270	if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_SET, dirty, NULL, 0) == -1) {
271		return errno;
272	}
273
274	return 0;
275}
276
277int
278proc_get_dirty(pid_t pid, uint32_t *flags)
279{
280	int retval;
281
282	if (!flags) {
283		return EINVAL;
284	}
285
286	retval = __proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_GET, 0, NULL, 0);
287	if (retval == -1) {
288		return errno;
289	}
290
291	*flags = retval;
292
293	return 0;
294}
295
296int
297proc_terminate(pid_t pid, int *sig)
298{
299	int retval;
300
301	if (!sig) {
302		return EINVAL;
303	}
304
305	retval = __proc_info(PROC_INFO_CALL_TERMINATE, pid, 0, 0, NULL, 0);
306	if (retval == -1) {
307		return errno;
308	}
309
310	*sig = retval;
311
312	return 0;
313}
314
315int
316proc_set_cpumon_params(pid_t pid, int percentage, int interval)
317{
318	proc_policy_cpuusage_attr_t attr;
319
320	attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
321	attr.ppattr_cpu_percentage = percentage;
322	attr.ppattr_cpu_attr_interval = (uint64_t)interval;
323	attr.ppattr_cpu_attr_deadline = 0;
324
325	return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
326		PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
327}
328
329int
330proc_get_cpumon_params(pid_t pid, int *percentage, int *interval)
331{
332	proc_policy_cpuusage_attr_t attr;
333	int ret;
334
335	ret = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_RESOURCE_USAGE,
336		PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0);
337
338	if ((ret == 0) && (attr.ppattr_cpu_attr == PROC_POLICY_RSRCACT_NOTIFY_EXC)) {
339		*percentage = attr.ppattr_cpu_percentage;
340		*interval = attr.ppattr_cpu_attr_interval;
341	} else {
342		*percentage = 0;
343		*interval = 0;
344	}
345
346	return (ret);
347}
348
349int
350proc_set_cpumon_defaults(pid_t pid)
351{
352	proc_policy_cpuusage_attr_t attr;
353
354	attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
355	attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DEFAULTS;
356	attr.ppattr_cpu_attr_interval = 0;
357	attr.ppattr_cpu_attr_deadline = 0;
358
359	return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
360		PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
361}
362
363int
364proc_disable_cpumon(pid_t pid)
365{
366	proc_policy_cpuusage_attr_t attr;
367
368	attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
369	attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DISABLE;
370	attr.ppattr_cpu_attr_interval = 0;
371	attr.ppattr_cpu_attr_deadline = 0;
372
373	return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
374		PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
375}
376
377int
378proc_set_wakemon_params(pid_t pid, int rate_hz, int flags __unused)
379{
380	struct proc_rlimit_control_wakeupmon params;
381
382	params.wm_flags = WAKEMON_ENABLE;
383	params.wm_rate = rate_hz;
384
385	return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
386}
387
388#ifndef WAKEMON_GET_PARAMS
389#define WAKEMON_GET_PARAMS 0x4
390#define WAKEMON_SET_DEFAULTS 0x8
391#endif
392
393int
394proc_get_wakemon_params(pid_t pid, int *rate_hz, int *flags)
395{
396	struct proc_rlimit_control_wakeupmon params;
397	int error;
398
399	params.wm_flags = WAKEMON_GET_PARAMS;
400
401	if ((error = proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params)) != 0) {
402		return (error);
403	}
404
405	*rate_hz = params.wm_rate;
406	*flags = params.wm_flags;
407
408	return (0);
409}
410
411int
412proc_set_wakemon_defaults(pid_t pid)
413{
414	struct proc_rlimit_control_wakeupmon params;
415
416	params.wm_flags = WAKEMON_ENABLE | WAKEMON_SET_DEFAULTS;
417	params.wm_rate = -1;
418
419	return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
420}
421
422int
423proc_disable_wakemon(pid_t pid)
424{
425	struct proc_rlimit_control_wakeupmon params;
426
427	params.wm_flags = WAKEMON_DISABLE;
428	params.wm_rate = -1;
429
430	return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
431}
432
433
434#if TARGET_OS_EMBEDDED
435
436int
437proc_setcpu_percentage(pid_t pid, int action, int percentage)
438{
439	proc_policy_cpuusage_attr_t attr;
440
441	bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
442	attr.ppattr_cpu_attr = action;
443	attr.ppattr_cpu_percentage = percentage;
444	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)
445		return(0);
446	else
447		return(errno);
448}
449
450int
451proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline)
452{
453	proc_policy_cpuusage_attr_t attr;
454
455	bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
456	attr.ppattr_cpu_attr = action;
457	attr.ppattr_cpu_attr_deadline = deadline;
458	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)
459		return(0);
460	else
461		return(errno);
462
463}
464
465
466int
467proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline)
468{
469	proc_policy_cpuusage_attr_t attr;
470
471	bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
472	attr.ppattr_cpu_attr = action;
473	attr.ppattr_cpu_percentage = percentage;
474	attr.ppattr_cpu_attr_deadline = deadline;
475	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)
476		return(0);
477	else
478		return(errno);
479}
480
481int
482proc_clear_cpulimits(pid_t pid)
483{
484	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)
485		return(0);
486	else
487		return(errno);
488
489
490}
491
492int
493proc_appstate(int pid, int * appstatep)
494{
495	int state;
496
497	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) {
498		if (appstatep != NULL)
499			*appstatep = state;
500		return(0);
501	 } else
502		return(errno);
503
504}
505
506
507int
508proc_setappstate(int pid, int appstate)
509{
510	int state = appstate;
511
512	switch (state) {
513		case PROC_APPSTATE_NONE:
514		case PROC_APPSTATE_ACTIVE:
515		case PROC_APPSTATE_INACTIVE:
516		case PROC_APPSTATE_BACKGROUND:
517		case PROC_APPSTATE_NONUI:
518			break;
519		default:
520			return(EINVAL);
521	}
522	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)
523		return(0);
524	else
525		return(errno);
526}
527
528int
529proc_devstatusnotify(int devicestatus)
530{
531	int state = devicestatus;
532
533	switch (devicestatus) {
534		case PROC_DEVSTATUS_SHORTTERM:
535		case PROC_DEVSTATUS_LONGTERM:
536			break;
537		default:
538			return(EINVAL);
539	}
540
541	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) {
542		return(0);
543	 } else
544		return(errno);
545
546}
547
548int
549proc_pidbind(int pid, uint64_t threadid, int bind)
550{
551	int state = bind;
552	pid_t passpid = pid;
553
554	switch (bind) {
555		case PROC_PIDBIND_CLEAR:
556			passpid = getpid();	/* ignore pid on clear */
557			break;
558		case PROC_PIDBIND_SET:
559			break;
560		default:
561			return(EINVAL);
562	}
563	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)
564		return(0);
565	else
566		return(errno);
567}
568#endif /* TARGET_OS_EMBEDDED */
569
570
571/* Donate importance to adaptive processes from this process */
572int
573proc_donate_importance_boost()
574{
575	int rval;
576
577#if TARGET_OS_EMBEDDED
578	rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
579							PROC_POLICY_ACTION_ENABLE,
580							PROC_POLICY_APPTYPE,
581							PROC_POLICY_IOS_DONATEIMP,
582							NULL, getpid(), (uint64_t)0);
583#else /* TARGET_OS_EMBEDDED */
584	rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
585							PROC_POLICY_ACTION_SET,
586							PROC_POLICY_BOOST,
587							PROC_POLICY_IMP_DONATION,
588							NULL, getpid(), 0);
589#endif /* TARGET_OS_EMBEDDED */
590
591	if (rval == 0)
592		return (0);
593	else
594		return (errno);
595}
596
597static __attribute__((noinline)) void
598proc_importance_bad_assertion(char *reason) {
599    (void)reason;
600}
601
602/*
603 * Use the address of these variables as the token.  This way, they can be
604 * printed in the debugger as useful names.
605 */
606uint64_t important_boost_assertion_token = 0xfafafafafafafafa;
607uint64_t normal_boost_assertion_token    = 0xfbfbfbfbfbfbfbfb;
608uint64_t non_boost_assertion_token       = 0xfcfcfcfcfcfcfcfc;
609
610/*
611 * Accept the boost on a message, or request another boost assertion
612 * if we have already accepted the implicit boost for this message.
613 *
614 * Returns EOVERFLOW if an attempt is made to take an extra assertion when not boosted.
615 *
616 * Returns EIO if the message was not a boosting message.
617 * TODO: Return a 'non-boost' token instead.
618 */
619int
620proc_importance_assertion_begin_with_msg(mach_msg_header_t  *msg,
621                                __unused mach_msg_trailer_t *trailer,
622                                         uint64_t           *assertion_token)
623{
624	int rval = 0;
625
626	if (assertion_token == NULL)
627		return (EINVAL);
628
629	/* Is this a boosting message? */
630	if ((msg->msgh_bits & MACH_MSGH_BITS_RAISEIMP) != 0) {
631
632		/*
633		 * Have we accepted the implicit boost for this message yet?
634		 * If we haven't accepted it yet, no need to call into kernel.
635		 */
636		if ((msg->msgh_bits & MACH_MSGH_BITS_IMPHOLDASRT) == 0) {
637			msg->msgh_bits |= MACH_MSGH_BITS_IMPHOLDASRT;
638			*assertion_token = (uint64_t) &important_boost_assertion_token;
639			return (0);
640		}
641
642		/* Request an additional boost count */
643
644#if TARGET_OS_EMBEDDED
645		rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
646								PROC_POLICY_ACTION_ENABLE,
647								PROC_POLICY_APPTYPE,
648								PROC_POLICY_IOS_HOLDIMP,
649								NULL, getpid(), 0);
650#else /* TARGET_OS_EMBEDDED */
651		rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
652								PROC_POLICY_ACTION_HOLD,
653								PROC_POLICY_BOOST,
654								PROC_POLICY_IMP_IMPORTANT,
655								NULL, getpid(), 0);
656#endif /* TARGET_OS_EMBEDDED */
657
658		if (rval == 0) {
659			*assertion_token = (uint64_t) &important_boost_assertion_token;
660			return (0);
661		} else if (errno == EOVERFLOW) {
662			proc_importance_bad_assertion("Attempted to take assertion while not boosted");
663			return (errno);
664		} else {
665			return (errno);
666		}
667	}
668
669	return (EIO);
670}
671
672
673/*
674 * Drop a boost assertion.
675 * Returns EOVERFLOW on boost assertion underflow.
676 */
677int
678proc_importance_assertion_complete(uint64_t assertion_token)
679{
680	int rval = 0;
681
682	if (assertion_token == 0)
683		return (0);
684
685	if (assertion_token == (uint64_t) &important_boost_assertion_token) {
686
687#if TARGET_OS_EMBEDDED
688		rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
689								PROC_POLICY_ACTION_ENABLE,
690								PROC_POLICY_APPTYPE,
691								PROC_POLICY_IOS_DROPIMP,
692								NULL, getpid(), 0);
693#else /* TARGET_OS_EMBEDDED */
694		rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
695								PROC_POLICY_ACTION_DROP,
696								PROC_POLICY_BOOST,
697								PROC_POLICY_IMP_IMPORTANT,
698								NULL, getpid(), 0);
699#endif /* TARGET_OS_EMBEDDED */
700
701		if (rval == 0) {
702			return (0);
703		} else if (errno == EOVERFLOW) {
704			proc_importance_bad_assertion("Attempted to drop too many assertions");
705			return (errno);
706		} else {
707			return (errno);
708		}
709	} else {
710		proc_importance_bad_assertion("Attempted to drop assertion with invalid token");
711		return (EIO);
712	}
713}
714
715#if !TARGET_OS_EMBEDDED
716
717int
718proc_clear_vmpressure(pid_t pid)
719{
720	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)
721		return(0);
722	else
723		return(errno);
724}
725
726/* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */
727int
728proc_set_owner_vmpressure(void)
729{
730	int retval;
731
732	if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1)
733		return(errno);
734
735	return(0);
736}
737
738/* mark yourself to delay idle sleep on disk IO */
739int
740proc_set_delayidlesleep(void)
741{
742	int retval;
743
744	if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)1, NULL, 0)) == -1)
745		return(errno);
746
747	return(0);
748}
749
750/* Reset yourself to delay idle sleep on disk IO, if already set */
751int
752proc_clear_delayidlesleep(void)
753{
754	int retval;
755
756	if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)0, NULL, 0)) == -1)
757		return(errno);
758
759	return(0);
760}
761
762/* disable the launch time backgroudn policy and restore the process to default group */
763int
764proc_disable_apptype(pid_t pid, int apptype)
765{
766	switch (apptype) {
767		case PROC_POLICY_OSX_APPTYPE_TAL:
768		case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
769			break;
770		default:
771			return(EINVAL);
772	}
773
774	if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
775		return(0);
776	else
777		return(errno);
778
779}
780
781/* re-enable the launch time background policy if it had been disabled. */
782int
783proc_enable_apptype(pid_t pid, int apptype)
784{
785	switch (apptype) {
786		case PROC_POLICY_OSX_APPTYPE_TAL:
787		case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
788			break;
789		default:
790			return(EINVAL);
791
792	}
793
794	if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
795		return(0);
796	else
797		return(errno);
798
799}
800
801#if !TARGET_IPHONE_SIMULATOR
802
803int
804proc_suppress(__unused pid_t pid, __unused uint64_t *generation)
805{
806	return 0;
807}
808
809#endif /* !TARGET_IPHONE_SIMULATOR */
810
811#endif /* !TARGET_OS_EMBEDDED */
812
813
814
815