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