]> git.saurik.com Git - apple/xnu.git/blob - libsyscall/wrappers/libproc/libproc.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / libsyscall / wrappers / libproc / libproc.c
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 <stdlib.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>
36
37 #include "libproc_internal.h"
38
39 int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
40 __private_extern__ int proc_setthreadname(void * buffer, int buffersize);
41 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);
42 int proc_rlimit_control(pid_t pid, int flavor, void *arg);
43
44 int
45 proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize)
46 {
47 int retval;
48
49 if ((type >= PROC_ALL_PIDS) || (type <= PROC_PPID_ONLY)) {
50 if ((retval = __proc_info(PROC_INFO_CALL_LISTPIDS, type, typeinfo,(uint64_t)0, buffer, buffersize)) == -1)
51 return(0);
52 } else {
53 errno = EINVAL;
54 retval = 0;
55 }
56 return(retval);
57 }
58
59
60 int
61 proc_listallpids(void * buffer, int buffersize)
62 {
63 int numpids;
64 numpids = proc_listpids(PROC_ALL_PIDS, (uint32_t)0, buffer, buffersize);
65
66 if (numpids == -1)
67 return(-1);
68 else
69 return(numpids/sizeof(int));
70 }
71
72 int
73 proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize)
74 {
75 int numpids;
76 numpids = proc_listpids(PROC_PGRP_ONLY, (uint32_t)pgrpid, buffer, buffersize);
77 if (numpids == -1)
78 return(-1);
79 else
80 return(numpids/sizeof(int));
81 }
82
83 int
84 proc_listchildpids(pid_t ppid, void * buffer, int buffersize)
85 {
86 int numpids;
87 numpids = proc_listpids(PROC_PPID_ONLY, (uint32_t)ppid, buffer, buffersize);
88 if (numpids == -1)
89 return(-1);
90 else
91 return(numpids/sizeof(int));
92 }
93
94
95 int
96 proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize)
97 {
98 int retval;
99
100 if ((retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor, arg, buffer, buffersize)) == -1)
101 return(0);
102
103 return(retval);
104 }
105
106
107 int
108 proc_pidoriginatorinfo(int flavor, void *buffer, int buffersize)
109 {
110 int retval;
111
112 if ((retval = __proc_info(PROC_INFO_CALL_PIDORIGINATORINFO, getpid(), flavor, 0, buffer, buffersize)) == -1)
113 return(0);
114
115 return(retval);
116 }
117
118 int
119 proc_listcoalitions(int flavor, int coaltype, void *buffer, int buffersize)
120 {
121 int retval;
122
123 if ((retval = __proc_info(PROC_INFO_CALL_LISTCOALITIONS, flavor, coaltype, 0, buffer, buffersize)) == -1)
124 return 0;
125
126 return retval;
127 }
128
129 int
130 proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer)
131 {
132 return (__proc_info(PROC_INFO_CALL_PIDRUSAGE, pid, flavor, 0, buffer, 0));
133 }
134
135 int
136 proc_setthread_cpupercent(uint8_t percentage, uint32_t ms_refill)
137 {
138 uint32_t arg = 0;
139
140 /* Pack percentage and refill into a 32-bit number to match existing kernel implementation */
141 if ((percentage >= 100) || (ms_refill & ~0xffffffU)) {
142 errno = EINVAL;
143 return -1;
144 }
145
146 arg = ((ms_refill << 8) | percentage);
147
148 return (proc_rlimit_control(-1, RLIMIT_THREAD_CPULIMITS, (void *)(uintptr_t)arg));
149 }
150
151 int
152 proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)
153 {
154 int retval;
155
156 if ((retval = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, flavor, (uint64_t)fd, buffer, buffersize)) == -1)
157 return(0);
158
159 return (retval);
160 }
161
162
163 int
164 proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize)
165 {
166 int retval;
167
168 if ((retval = __proc_info(PROC_INFO_CALL_PIDFILEPORTINFO, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1)
169 return (0);
170 return (retval);
171 }
172
173
174 int
175 proc_name(int pid, void * buffer, uint32_t buffersize)
176 {
177 int retval = 0, len;
178 struct proc_bsdinfo pbsd;
179
180
181 if (buffersize < sizeof(pbsd.pbi_name)) {
182 errno = ENOMEM;
183 return(0);
184 }
185
186 retval = proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &pbsd, sizeof(struct proc_bsdinfo));
187 if (retval != 0) {
188 if (pbsd.pbi_name[0]) {
189 bcopy(&pbsd.pbi_name, buffer, sizeof(pbsd.pbi_name));
190 } else {
191 bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm));
192 }
193 len = (int)strlen(buffer);
194 return(len);
195 }
196 return(0);
197 }
198
199 int
200 proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)
201 {
202 int retval = 0, len;
203 struct proc_regionwithpathinfo reginfo;
204
205 if (buffersize < MAXPATHLEN) {
206 errno = ENOMEM;
207 return(0);
208 }
209
210 retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, &reginfo, sizeof(struct proc_regionwithpathinfo));
211 if (retval != -1) {
212 len = (int)strlen(&reginfo.prp_vip.vip_path[0]);
213 if (len != 0) {
214 if (len > MAXPATHLEN)
215 len = MAXPATHLEN;
216 bcopy(&reginfo.prp_vip.vip_path[0], buffer, len);
217 return(len);
218 }
219 return(0);
220 }
221 return(0);
222
223 }
224
225 int
226 proc_kmsgbuf(void * buffer, uint32_t buffersize)
227 {
228 int retval;
229
230 if ((retval = __proc_info(PROC_INFO_CALL_KERNMSGBUF, 0, 0, (uint64_t)0, buffer, buffersize)) == -1)
231 return(0);
232 return (retval);
233 }
234
235 int
236 proc_pidpath(int pid, void * buffer, uint32_t buffersize)
237 {
238 int retval, len;
239
240 if (buffersize < PROC_PIDPATHINFO_SIZE) {
241 errno = ENOMEM;
242 return(0);
243 }
244 if (buffersize > PROC_PIDPATHINFO_MAXSIZE) {
245 errno = EOVERFLOW;
246 return(0);
247 }
248
249 retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize);
250 if (retval != -1) {
251 len = (int)strlen(buffer);
252 return(len);
253 }
254 return (0);
255 }
256
257
258 int
259 proc_libversion(int *major, int * minor)
260 {
261
262 if (major != NULL)
263 *major = 1;
264 if (minor != NULL)
265 *minor = 1;
266 return(0);
267 }
268
269 int
270 proc_setpcontrol(const int control)
271 {
272 int retval ;
273
274 if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE)
275 return(EINVAL);
276
277 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1)
278 return(errno);
279
280 return(0);
281 }
282
283
284 __private_extern__ int
285 proc_setthreadname(void * buffer, int buffersize)
286 {
287 int retval;
288
289 retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize);
290
291 if (retval == -1)
292 return(errno);
293 else
294 return(0);
295 }
296
297 int
298 proc_track_dirty(pid_t pid, uint32_t flags)
299 {
300 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_TRACK, flags, NULL, 0) == -1) {
301 return errno;
302 }
303
304 return 0;
305 }
306
307 int
308 proc_set_dirty(pid_t pid, bool dirty)
309 {
310 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_SET, dirty, NULL, 0) == -1) {
311 return errno;
312 }
313
314 return 0;
315 }
316
317 int
318 proc_get_dirty(pid_t pid, uint32_t *flags)
319 {
320 int retval;
321
322 if (!flags) {
323 return EINVAL;
324 }
325
326 retval = __proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_GET, 0, NULL, 0);
327 if (retval == -1) {
328 return errno;
329 }
330
331 *flags = retval;
332
333 return 0;
334 }
335
336 int
337 proc_clear_dirty(pid_t pid, uint32_t flags)
338 {
339 if (__proc_info(PROC_INFO_CALL_DIRTYCONTROL, pid, PROC_DIRTYCONTROL_CLEAR, flags, NULL, 0) == -1) {
340 return errno;
341 }
342
343 return 0;
344 }
345
346 int
347 proc_terminate(pid_t pid, int *sig)
348 {
349 int retval;
350
351 if (!sig) {
352 return EINVAL;
353 }
354
355 retval = __proc_info(PROC_INFO_CALL_TERMINATE, pid, 0, 0, NULL, 0);
356 if (retval == -1) {
357 return errno;
358 }
359
360 *sig = retval;
361
362 return 0;
363 }
364
365 int
366 proc_set_cpumon_params(pid_t pid, int percentage, int interval)
367 {
368 proc_policy_cpuusage_attr_t attr;
369
370 attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
371 attr.ppattr_cpu_percentage = percentage;
372 attr.ppattr_cpu_attr_interval = (uint64_t)interval;
373 attr.ppattr_cpu_attr_deadline = 0;
374
375 return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
376 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
377 }
378
379 int
380 proc_get_cpumon_params(pid_t pid, int *percentage, int *interval)
381 {
382 proc_policy_cpuusage_attr_t attr;
383 int ret;
384
385 ret = __process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_RESOURCE_USAGE,
386 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0);
387
388 if ((ret == 0) && (attr.ppattr_cpu_attr == PROC_POLICY_RSRCACT_NOTIFY_EXC)) {
389 *percentage = attr.ppattr_cpu_percentage;
390 *interval = (int)attr.ppattr_cpu_attr_interval;
391 } else {
392 *percentage = 0;
393 *interval = 0;
394 }
395
396 return (ret);
397 }
398
399 int
400 proc_set_cpumon_defaults(pid_t pid)
401 {
402 proc_policy_cpuusage_attr_t attr;
403
404 attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
405 attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DEFAULTS;
406 attr.ppattr_cpu_attr_interval = 0;
407 attr.ppattr_cpu_attr_deadline = 0;
408
409 return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
410 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
411 }
412
413 int
414 proc_disable_cpumon(pid_t pid)
415 {
416 proc_policy_cpuusage_attr_t attr;
417
418 attr.ppattr_cpu_attr = PROC_POLICY_RSRCACT_NOTIFY_EXC;
419 attr.ppattr_cpu_percentage = PROC_POLICY_CPUMON_DISABLE;
420 attr.ppattr_cpu_attr_interval = 0;
421 attr.ppattr_cpu_attr_deadline = 0;
422
423 return(__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_SET, PROC_POLICY_RESOURCE_USAGE,
424 PROC_POLICY_RUSAGE_CPU, (proc_policy_attribute_t*)&attr, pid, 0));
425 }
426
427
428 /*
429 * Turn on the CPU usage monitor using the supplied parameters, and make
430 * violations of the monitor fatal.
431 *
432 * Returns: 0 on success;
433 * -1 on failure and sets errno
434 */
435 int
436 proc_set_cpumon_params_fatal(pid_t pid, int percentage, int interval)
437 {
438 int current_percentage = 0;
439 int current_interval = 0; /* intervals are in seconds */
440 int ret = 0;
441
442 if ((percentage <= 0) || (interval <= 0)) {
443 errno = EINVAL;
444 return (-1);
445 }
446
447 /*
448 * Do a simple query to see if CPU monitoring is
449 * already active. If either the percentage or the
450 * interval is nonzero, then CPU monitoring is
451 * already in use for this process.
452 */
453 (void)proc_get_cpumon_params(pid, &current_percentage, &current_interval);
454 if (current_percentage || current_interval)
455 {
456 /*
457 * The CPU monitor appears to be active.
458 * We choose not to disturb those settings.
459 */
460 errno = EBUSY;
461 return (-1);
462 }
463
464 if ((ret = proc_set_cpumon_params(pid, percentage, interval)) != 0) {
465 /* Failed to activate the CPU monitor */
466 return (ret);
467 }
468
469 if ((ret = proc_rlimit_control(pid, RLIMIT_CPU_USAGE_MONITOR, CPUMON_MAKE_FATAL)) != 0) {
470 /* Failed to set termination, back out the CPU monitor settings. */
471 (void)proc_disable_cpumon(pid);
472 }
473
474 return (ret);
475 }
476
477 int
478 proc_set_wakemon_params(pid_t pid, int rate_hz, int flags __unused)
479 {
480 struct proc_rlimit_control_wakeupmon params;
481
482 params.wm_flags = WAKEMON_ENABLE;
483 params.wm_rate = rate_hz;
484
485 return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
486 }
487
488 #ifndef WAKEMON_GET_PARAMS
489 #define WAKEMON_GET_PARAMS 0x4
490 #define WAKEMON_SET_DEFAULTS 0x8
491 #endif
492
493 int
494 proc_get_wakemon_params(pid_t pid, int *rate_hz, int *flags)
495 {
496 struct proc_rlimit_control_wakeupmon params;
497 int error;
498
499 params.wm_flags = WAKEMON_GET_PARAMS;
500
501 if ((error = proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params)) != 0) {
502 return (error);
503 }
504
505 *rate_hz = params.wm_rate;
506 *flags = params.wm_flags;
507
508 return (0);
509 }
510
511 int
512 proc_set_wakemon_defaults(pid_t pid)
513 {
514 struct proc_rlimit_control_wakeupmon params;
515
516 params.wm_flags = WAKEMON_ENABLE | WAKEMON_SET_DEFAULTS;
517 params.wm_rate = -1;
518
519 return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
520 }
521
522 int
523 proc_disable_wakemon(pid_t pid)
524 {
525 struct proc_rlimit_control_wakeupmon params;
526
527 params.wm_flags = WAKEMON_DISABLE;
528 params.wm_rate = -1;
529
530 return (proc_rlimit_control(pid, RLIMIT_WAKEUPS_MONITOR, &params));
531 }
532
533 int
534 proc_list_uptrs(int pid, uint64_t *buf, uint32_t bufsz)
535 {
536 int i, j;
537 int nfds, nkns;
538 int count = 0;
539 int knote_max = 4096; /* arbitrary starting point */
540
541 /* if buffer is empty, this call simply counts the knotes */
542 if (bufsz > 0 && buf == NULL) {
543 errno = EFAULT;
544 return -1;
545 }
546
547 struct proc_fdinfo fdlist[OPEN_MAX];
548 nfds = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdlist, OPEN_MAX*sizeof(struct proc_fdinfo));
549 if (nfds <= 0 || nfds > OPEN_MAX) {
550 return -1;
551 }
552
553 struct kevent_extinfo *kqext = malloc(knote_max * sizeof(struct kevent_extinfo));
554 if (!kqext) {
555 errno = ENOMEM;
556 return -1;
557 }
558
559 for (i = 0; i < nfds; i++) {
560 if (fdlist[i].proc_fdtype != PROX_FDTYPE_KQUEUE) {
561 continue;
562 }
563
564 again:
565 nkns = __proc_info(PROC_INFO_CALL_PIDFDINFO, pid, PROC_PIDFDKQUEUE_EXTINFO,
566 (uint64_t)fdlist[i].proc_fd, kqext, knote_max * sizeof(struct kevent_extinfo));
567 if (nkns < 0) {
568 if (errno == EBADF) {
569 /* the FD table can change after enumerating the FDs */
570 errno = EAGAIN;
571 }
572 free(kqext);
573 return -1;
574 }
575
576 if (nkns > knote_max) {
577 /* there are more knotes than we requested - try again with a
578 * larger buffer */
579 free(kqext);
580 knote_max = nkns + 32; /* small margin in case of extra knotes */
581 kqext = malloc(knote_max * sizeof(struct kevent_extinfo));
582 if (!kqext) {
583 errno = ENOMEM;
584 return -1;
585 }
586 goto again;
587 }
588
589 for (j = 0; j < nkns; j++) {
590 if (kqext[j].kqext_kev.udata == 0) {
591 continue;
592 }
593
594 if (bufsz >= sizeof(uint64_t)) {
595 *buf++ = kqext[j].kqext_kev.udata;
596 bufsz -= sizeof(uint64_t);
597 }
598 count++;
599 }
600 }
601
602 free(kqext);
603 return count;
604 }
605
606
607
608 /* Donate importance to adaptive processes from this process */
609 int
610 proc_donate_importance_boost()
611 {
612 int rval;
613
614 rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
615 PROC_POLICY_ACTION_SET,
616 PROC_POLICY_BOOST,
617 PROC_POLICY_IMP_DONATION,
618 NULL, getpid(), 0);
619
620 if (rval == 0)
621 return (0);
622 else
623 return (errno);
624 }
625
626 static __attribute__((noinline)) void
627 proc_importance_bad_assertion(char *reason) {
628 (void)reason;
629 }
630
631 /*
632 * Use the address of these variables as the token. This way, they can be
633 * printed in the debugger as useful names.
634 */
635 uint64_t important_boost_assertion_token = 0xfafafafafafafafa;
636 uint64_t normal_boost_assertion_token = 0xfbfbfbfbfbfbfbfb;
637 uint64_t non_boost_assertion_token = 0xfcfcfcfcfcfcfcfc;
638 uint64_t denap_boost_assertion_token = 0xfdfdfdfdfdfdfdfd;
639
640 /*
641 * Accept the boost on a message, or request another boost assertion
642 * if we have already accepted the implicit boost for this message.
643 *
644 * Returns EOVERFLOW if an attempt is made to take an extra assertion when not boosted.
645 *
646 * Returns EIO if the message was not a boosting message.
647 * TODO: Return a 'non-boost' token instead.
648 */
649 int
650 proc_importance_assertion_begin_with_msg(mach_msg_header_t *msg,
651 __unused mach_msg_trailer_t *trailer,
652 uint64_t *assertion_token)
653 {
654 int rval = 0;
655
656 if (assertion_token == NULL)
657 return (EINVAL);
658
659 #define LEGACYBOOSTMASK (MACH_MSGH_BITS_VOUCHER_MASK | MACH_MSGH_BITS_RAISEIMP)
660 #define LEGACYBOOSTED(m) (((m)->msgh_bits & LEGACYBOOSTMASK) == MACH_MSGH_BITS_RAISEIMP)
661
662 /* Is this a legacy boosted message? */
663 if (LEGACYBOOSTED(msg)) {
664
665 /*
666 * Have we accepted the implicit boost for this message yet?
667 * If we haven't accepted it yet, no need to call into kernel.
668 */
669 if ((msg->msgh_bits & MACH_MSGH_BITS_IMPHOLDASRT) == 0) {
670 msg->msgh_bits |= MACH_MSGH_BITS_IMPHOLDASRT;
671 *assertion_token = (uint64_t) &important_boost_assertion_token;
672 return (0);
673 }
674
675 /* Request an additional boost count */
676 rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
677 PROC_POLICY_ACTION_HOLD,
678 PROC_POLICY_BOOST,
679 PROC_POLICY_IMP_IMPORTANT,
680 NULL, getpid(), 0);
681 if (rval == 0) {
682 *assertion_token = (uint64_t) &important_boost_assertion_token;
683 return (0);
684 } else if (errno == EOVERFLOW) {
685 proc_importance_bad_assertion("Attempted to take assertion while not boosted");
686 return (errno);
687 } else {
688 return (errno);
689 }
690 }
691
692 return (EIO);
693 }
694
695
696 /*
697 * Drop a boost assertion.
698 * Returns EOVERFLOW on boost assertion underflow.
699 */
700 int
701 proc_importance_assertion_complete(uint64_t assertion_token)
702 {
703 int rval = 0;
704
705 if (assertion_token == 0)
706 return (0);
707
708 if (assertion_token == (uint64_t) &important_boost_assertion_token) {
709 rval = __process_policy(PROC_POLICY_SCOPE_PROCESS,
710 PROC_POLICY_ACTION_DROP,
711 PROC_POLICY_BOOST,
712 PROC_POLICY_IMP_IMPORTANT,
713 NULL, getpid(), 0);
714 if (rval == 0) {
715 return (0);
716 } else if (errno == EOVERFLOW) {
717 proc_importance_bad_assertion("Attempted to drop too many assertions");
718 return (errno);
719 } else {
720 return (errno);
721 }
722 } else {
723 proc_importance_bad_assertion("Attempted to drop assertion with invalid token");
724 return (EIO);
725 }
726 }
727
728 /*
729 * Accept the De-Nap boost on a message, or request another boost assertion
730 * if we have already accepted the implicit boost for this message.
731 *
732 * Interface is deprecated before it really got started - just as synonym
733 * for proc_importance_assertion_begin_with_msg() now.
734 */
735 int
736 proc_denap_assertion_begin_with_msg(mach_msg_header_t *msg,
737 uint64_t *assertion_token)
738 {
739 #pragma clang diagnostic push
740 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
741 return proc_importance_assertion_begin_with_msg(msg, NULL, assertion_token);
742 #pragma clang diagnostic pop
743 }
744
745
746 /*
747 * Drop a denap boost assertion.
748 *
749 * Interface is deprecated before it really got started - just a synonym
750 * for proc_importance_assertion_complete() now.
751 */
752 int
753 proc_denap_assertion_complete(uint64_t assertion_token)
754 {
755 return proc_importance_assertion_complete(assertion_token);
756 }
757
758
759 int
760 proc_clear_vmpressure(pid_t pid)
761 {
762 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)
763 return(0);
764 else
765 return(errno);
766 }
767
768 /* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */
769 int
770 proc_set_owner_vmpressure(void)
771 {
772 int retval;
773
774 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1)
775 return(errno);
776
777 return(0);
778 }
779
780 /* mark yourself to delay idle sleep on disk IO */
781 int
782 proc_set_delayidlesleep(void)
783 {
784 int retval;
785
786 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)1, NULL, 0)) == -1)
787 return(errno);
788
789 return(0);
790 }
791
792 /* Reset yourself to delay idle sleep on disk IO, if already set */
793 int
794 proc_clear_delayidlesleep(void)
795 {
796 int retval;
797
798 if ((retval = __proc_info(PROC_INFO_CALL_SETCONTROL, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)0, NULL, 0)) == -1)
799 return(errno);
800
801 return(0);
802 }
803
804 /* disable the launch time backgroudn policy and restore the process to default group */
805 int
806 proc_disable_apptype(pid_t pid, int apptype)
807 {
808 switch (apptype) {
809 case PROC_POLICY_OSX_APPTYPE_TAL:
810 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
811 break;
812 default:
813 return(EINVAL);
814 }
815
816 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
817 return(0);
818 else
819 return(errno);
820
821 }
822
823 /* re-enable the launch time background policy if it had been disabled. */
824 int
825 proc_enable_apptype(pid_t pid, int apptype)
826 {
827 switch (apptype) {
828 case PROC_POLICY_OSX_APPTYPE_TAL:
829 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
830 break;
831 default:
832 return(EINVAL);
833
834 }
835
836 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
837 return(0);
838 else
839 return(errno);
840
841 }
842
843 #if !TARGET_IPHONE_SIMULATOR
844
845 int
846 proc_suppress(__unused pid_t pid, __unused uint64_t *generation)
847 {
848 return 0;
849 }
850
851 #endif /* !TARGET_IPHONE_SIMULATOR */
852
853
854
855