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, ®info, sizeof(struct proc_regionwithpathinfo)); 171 if (retval != -1) { 172 len = strlen(®info.prp_vip.vip_path[0]); 173 if (len != 0) { 174 if (len > MAXPATHLEN) 175 len = MAXPATHLEN; 176 bcopy(®info.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, ¶ms)); 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, ¶ms)) != 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, ¶ms)); 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, ¶ms)); 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