1/* 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_FREE_COPYRIGHT@ 30 */ 31/* 32 * Copyright (c) 1993 The University of Utah and 33 * the Center for Software Science (CSS). All rights reserved. 34 * 35 * Permission to use, copy, modify and distribute this software and its 36 * documentation is hereby granted, provided that both the copyright 37 * notice and this permission notice appear in all copies of the 38 * software, derivative works or modified versions, and any portions 39 * thereof, and that both notices appear in supporting documentation. 40 * 41 * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS 42 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF 43 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 44 * 45 * CSS requests users of this software to return to css-dist@cs.utah.edu any 46 * improvements that they make and grant CSS redistribution rights. 47 * 48 * Author: Bryan Ford, University of Utah CSS 49 * 50 * Thread management routines 51 */ 52#include <mach/mach_types.h> 53#include <mach/kern_return.h> 54#include <mach/alert.h> 55#include <mach/rpc.h> 56#include <mach/thread_act_server.h> 57 58#include <kern/kern_types.h> 59#include <kern/ast.h> 60#include <kern/mach_param.h> 61#include <kern/zalloc.h> 62#include <kern/extmod_statistics.h> 63#include <kern/thread.h> 64#include <kern/task.h> 65#include <kern/sched_prim.h> 66#include <kern/misc_protos.h> 67#include <kern/assert.h> 68#include <kern/exception.h> 69#include <kern/ipc_mig.h> 70#include <kern/ipc_tt.h> 71#include <kern/machine.h> 72#include <kern/spl.h> 73#include <kern/syscall_subr.h> 74#include <kern/sync_lock.h> 75#include <kern/processor.h> 76#include <kern/timer.h> 77#include <kern/affinity.h> 78 79#include <mach/rpc.h> 80 81#include <security/mac_mach_internal.h> 82 83void act_abort(thread_t); 84void install_special_handler_locked(thread_t); 85void special_handler_continue(void); 86 87/* 88 * Internal routine to mark a thread as started. 89 * Always called with the thread locked. 90 * 91 * Note: function intentionally declared with the noinline attribute to 92 * prevent multiple declaration of probe symbols in this file; we would 93 * prefer "#pragma noinline", but gcc does not support it. 94 * PR-6385749 -- the lwp-start probe should fire from within the context 95 * of the newly created thread. Commented out for now, in case we 96 * turn it into a dead code probe. 97 */ 98void 99thread_start_internal( 100 thread_t thread) 101{ 102 clear_wait(thread, THREAD_AWAKENED); 103 thread->started = TRUE; 104 // DTRACE_PROC1(lwp__start, thread_t, thread); 105} 106 107/* 108 * Internal routine to terminate a thread. 109 * Sometimes called with task already locked. 110 */ 111kern_return_t 112thread_terminate_internal( 113 thread_t thread) 114{ 115 kern_return_t result = KERN_SUCCESS; 116 117 thread_mtx_lock(thread); 118 119 if (thread->active) { 120 thread->active = FALSE; 121 122 act_abort(thread); 123 124 if (thread->started) 125 clear_wait(thread, THREAD_INTERRUPTED); 126 else { 127 thread_start_internal(thread); 128 } 129 } 130 else 131 result = KERN_TERMINATED; 132 133 if (thread->affinity_set != NULL) 134 thread_affinity_terminate(thread); 135 136 thread_mtx_unlock(thread); 137 138 if (thread != current_thread() && result == KERN_SUCCESS) 139 thread_wait(thread, FALSE); 140 141 return (result); 142} 143 144/* 145 * Terminate a thread. 146 */ 147kern_return_t 148thread_terminate( 149 thread_t thread) 150{ 151 kern_return_t result; 152 153 if (thread == THREAD_NULL) 154 return (KERN_INVALID_ARGUMENT); 155 156 if ( thread->task == kernel_task && 157 thread != current_thread() ) 158 return (KERN_FAILURE); 159 160 result = thread_terminate_internal(thread); 161 162 /* 163 * If a kernel thread is terminating itself, force an AST here. 164 * Kernel threads don't normally pass through the AST checking 165 * code - and all threads finish their own termination in the 166 * special handler APC. 167 */ 168 if (thread->task == kernel_task) { 169 ml_set_interrupts_enabled(FALSE); 170 ast_taken(AST_APC, TRUE); 171 panic("thread_terminate"); 172 } 173 174 return (result); 175} 176 177/* 178 * Suspend execution of the specified thread. 179 * This is a recursive-style suspension of the thread, a count of 180 * suspends is maintained. 181 * 182 * Called with thread mutex held. 183 */ 184void 185thread_hold( 186 register thread_t thread) 187{ 188 if (thread->suspend_count++ == 0) { 189 install_special_handler(thread); 190 if (thread->started) 191 thread_wakeup_one(&thread->suspend_count); 192 } 193} 194 195/* 196 * Decrement internal suspension count, setting thread 197 * runnable when count falls to zero. 198 * 199 * Called with thread mutex held. 200 */ 201void 202thread_release( 203 register thread_t thread) 204{ 205 if ( thread->suspend_count > 0 && 206 --thread->suspend_count == 0 ) { 207 if (thread->started) 208 thread_wakeup_one(&thread->suspend_count); 209 else { 210 thread_start_internal(thread); 211 } 212 } 213} 214 215kern_return_t 216thread_suspend( 217 register thread_t thread) 218{ 219 thread_t self = current_thread(); 220 kern_return_t result = KERN_SUCCESS; 221 222 if (thread == THREAD_NULL || thread->task == kernel_task) 223 return (KERN_INVALID_ARGUMENT); 224 225 thread_mtx_lock(thread); 226 227 if (thread->active) { 228 if ( thread->user_stop_count++ == 0 && 229 thread->suspend_count++ == 0 ) { 230 install_special_handler(thread); 231 if (thread != self) 232 thread_wakeup_one(&thread->suspend_count); 233 } 234 } 235 else 236 result = KERN_TERMINATED; 237 238 thread_mtx_unlock(thread); 239 240 if (thread != self && result == KERN_SUCCESS) 241 thread_wait(thread, TRUE); 242 243 return (result); 244} 245 246kern_return_t 247thread_resume( 248 register thread_t thread) 249{ 250 kern_return_t result = KERN_SUCCESS; 251 252 if (thread == THREAD_NULL || thread->task == kernel_task) 253 return (KERN_INVALID_ARGUMENT); 254 255 thread_mtx_lock(thread); 256 257 if (thread->active) { 258 if (thread->user_stop_count > 0) { 259 if ( --thread->user_stop_count == 0 && 260 --thread->suspend_count == 0 ) { 261 if (thread->started) 262 thread_wakeup_one(&thread->suspend_count); 263 else { 264 thread_start_internal(thread); 265 } 266 } 267 } 268 else 269 result = KERN_FAILURE; 270 } 271 else 272 result = KERN_TERMINATED; 273 274 thread_mtx_unlock(thread); 275 276 return (result); 277} 278 279/* 280 * thread_depress_abort: 281 * 282 * Prematurely abort priority depression if there is one. 283 */ 284kern_return_t 285thread_depress_abort( 286 register thread_t thread) 287{ 288 kern_return_t result; 289 290 if (thread == THREAD_NULL) 291 return (KERN_INVALID_ARGUMENT); 292 293 thread_mtx_lock(thread); 294 295 if (thread->active) 296 result = thread_depress_abort_internal(thread); 297 else 298 result = KERN_TERMINATED; 299 300 thread_mtx_unlock(thread); 301 302 return (result); 303} 304 305 306/* 307 * Indicate that the activation should run its 308 * special handler to detect a condition. 309 * 310 * Called with thread mutex held. 311 */ 312void 313act_abort( 314 thread_t thread) 315{ 316 spl_t s = splsched(); 317 318 thread_lock(thread); 319 320 if (!(thread->sched_flags & TH_SFLAG_ABORT)) { 321 thread->sched_flags |= TH_SFLAG_ABORT; 322 install_special_handler_locked(thread); 323 } 324 else 325 thread->sched_flags &= ~TH_SFLAG_ABORTSAFELY; 326 327 thread_unlock(thread); 328 splx(s); 329} 330 331kern_return_t 332thread_abort( 333 register thread_t thread) 334{ 335 kern_return_t result = KERN_SUCCESS; 336 337 if (thread == THREAD_NULL) 338 return (KERN_INVALID_ARGUMENT); 339 340 thread_mtx_lock(thread); 341 342 if (thread->active) { 343 act_abort(thread); 344 clear_wait(thread, THREAD_INTERRUPTED); 345 } 346 else 347 result = KERN_TERMINATED; 348 349 thread_mtx_unlock(thread); 350 351 return (result); 352} 353 354kern_return_t 355thread_abort_safely( 356 thread_t thread) 357{ 358 kern_return_t result = KERN_SUCCESS; 359 360 if (thread == THREAD_NULL) 361 return (KERN_INVALID_ARGUMENT); 362 363 thread_mtx_lock(thread); 364 365 if (thread->active) { 366 spl_t s = splsched(); 367 368 thread_lock(thread); 369 if (!thread->at_safe_point || 370 clear_wait_internal(thread, THREAD_INTERRUPTED) != KERN_SUCCESS) { 371 if (!(thread->sched_flags & TH_SFLAG_ABORT)) { 372 thread->sched_flags |= TH_SFLAG_ABORTED_MASK; 373 install_special_handler_locked(thread); 374 } 375 } 376 thread_unlock(thread); 377 splx(s); 378 } 379 else 380 result = KERN_TERMINATED; 381 382 thread_mtx_unlock(thread); 383 384 return (result); 385} 386 387/*** backward compatibility hacks ***/ 388#include <mach/thread_info.h> 389#include <mach/thread_special_ports.h> 390#include <ipc/ipc_port.h> 391 392kern_return_t 393thread_info( 394 thread_t thread, 395 thread_flavor_t flavor, 396 thread_info_t thread_info_out, 397 mach_msg_type_number_t *thread_info_count) 398{ 399 kern_return_t result; 400 401 if (thread == THREAD_NULL) 402 return (KERN_INVALID_ARGUMENT); 403 404 thread_mtx_lock(thread); 405 406 if (thread->active) 407 result = thread_info_internal( 408 thread, flavor, thread_info_out, thread_info_count); 409 else 410 result = KERN_TERMINATED; 411 412 thread_mtx_unlock(thread); 413 414 return (result); 415} 416 417kern_return_t 418thread_get_state( 419 register thread_t thread, 420 int flavor, 421 thread_state_t state, /* pointer to OUT array */ 422 mach_msg_type_number_t *state_count) /*IN/OUT*/ 423{ 424 kern_return_t result = KERN_SUCCESS; 425 426 if (thread == THREAD_NULL) 427 return (KERN_INVALID_ARGUMENT); 428 429 thread_mtx_lock(thread); 430 431 if (thread->active) { 432 if (thread != current_thread()) { 433 thread_hold(thread); 434 435 thread_mtx_unlock(thread); 436 437 if (thread_stop(thread)) { 438 thread_mtx_lock(thread); 439 result = machine_thread_get_state( 440 thread, flavor, state, state_count); 441 thread_unstop(thread); 442 } 443 else { 444 thread_mtx_lock(thread); 445 result = KERN_ABORTED; 446 } 447 448 thread_release(thread); 449 } 450 else 451 result = machine_thread_get_state( 452 thread, flavor, state, state_count); 453 } 454 else 455 result = KERN_TERMINATED; 456 457 thread_mtx_unlock(thread); 458 459 return (result); 460} 461 462/* 463 * Change thread's machine-dependent state. Called with nothing 464 * locked. Returns same way. 465 */ 466static kern_return_t 467thread_set_state_internal( 468 register thread_t thread, 469 int flavor, 470 thread_state_t state, 471 mach_msg_type_number_t state_count, 472 boolean_t from_user) 473{ 474 kern_return_t result = KERN_SUCCESS; 475 476 if (thread == THREAD_NULL) 477 return (KERN_INVALID_ARGUMENT); 478 479 thread_mtx_lock(thread); 480 481 if (thread->active) { 482 if (thread != current_thread()) { 483 thread_hold(thread); 484 485 thread_mtx_unlock(thread); 486 487 if (thread_stop(thread)) { 488 thread_mtx_lock(thread); 489 result = machine_thread_set_state( 490 thread, flavor, state, state_count); 491 thread_unstop(thread); 492 } 493 else { 494 thread_mtx_lock(thread); 495 result = KERN_ABORTED; 496 } 497 498 thread_release(thread); 499 } 500 else 501 result = machine_thread_set_state( 502 thread, flavor, state, state_count); 503 } 504 else 505 result = KERN_TERMINATED; 506 507 if ((result == KERN_SUCCESS) && from_user) 508 extmod_statistics_incr_thread_set_state(thread); 509 510 thread_mtx_unlock(thread); 511 512 return (result); 513} 514 515/* No prototype, since thread_act_server.h has the _from_user version if KERNEL_SERVER */ 516kern_return_t 517thread_set_state( 518 register thread_t thread, 519 int flavor, 520 thread_state_t state, 521 mach_msg_type_number_t state_count); 522 523kern_return_t 524thread_set_state( 525 register thread_t thread, 526 int flavor, 527 thread_state_t state, 528 mach_msg_type_number_t state_count) 529{ 530 return thread_set_state_internal(thread, flavor, state, state_count, FALSE); 531} 532 533kern_return_t 534thread_set_state_from_user( 535 register thread_t thread, 536 int flavor, 537 thread_state_t state, 538 mach_msg_type_number_t state_count) 539{ 540 return thread_set_state_internal(thread, flavor, state, state_count, TRUE); 541} 542 543/* 544 * Kernel-internal "thread" interfaces used outside this file: 545 */ 546 547/* Initialize (or re-initialize) a thread state. Called from execve 548 * with nothing locked, returns same way. 549 */ 550kern_return_t 551thread_state_initialize( 552 register thread_t thread) 553{ 554 kern_return_t result = KERN_SUCCESS; 555 556 if (thread == THREAD_NULL) 557 return (KERN_INVALID_ARGUMENT); 558 559 thread_mtx_lock(thread); 560 561 if (thread->active) { 562 if (thread != current_thread()) { 563 thread_hold(thread); 564 565 thread_mtx_unlock(thread); 566 567 if (thread_stop(thread)) { 568 thread_mtx_lock(thread); 569 result = machine_thread_state_initialize( thread ); 570 thread_unstop(thread); 571 } 572 else { 573 thread_mtx_lock(thread); 574 result = KERN_ABORTED; 575 } 576 577 thread_release(thread); 578 } 579 else 580 result = machine_thread_state_initialize( thread ); 581 } 582 else 583 result = KERN_TERMINATED; 584 585 thread_mtx_unlock(thread); 586 587 return (result); 588} 589 590 591kern_return_t 592thread_dup( 593 register thread_t target) 594{ 595 thread_t self = current_thread(); 596 kern_return_t result = KERN_SUCCESS; 597 598 if (target == THREAD_NULL || target == self) 599 return (KERN_INVALID_ARGUMENT); 600 601 thread_mtx_lock(target); 602 603 if (target->active) { 604 thread_hold(target); 605 606 thread_mtx_unlock(target); 607 608 if (thread_stop(target)) { 609 thread_mtx_lock(target); 610 result = machine_thread_dup(self, target); 611 if (self->affinity_set != AFFINITY_SET_NULL) 612 thread_affinity_dup(self, target); 613 thread_unstop(target); 614 } 615 else { 616 thread_mtx_lock(target); 617 result = KERN_ABORTED; 618 } 619 620 thread_release(target); 621 } 622 else 623 result = KERN_TERMINATED; 624 625 thread_mtx_unlock(target); 626 627 return (result); 628} 629 630 631/* 632 * thread_setstatus: 633 * 634 * Set the status of the specified thread. 635 * Called with (and returns with) no locks held. 636 */ 637kern_return_t 638thread_setstatus( 639 register thread_t thread, 640 int flavor, 641 thread_state_t tstate, 642 mach_msg_type_number_t count) 643{ 644 645 return (thread_set_state(thread, flavor, tstate, count)); 646} 647 648/* 649 * thread_getstatus: 650 * 651 * Get the status of the specified thread. 652 */ 653kern_return_t 654thread_getstatus( 655 register thread_t thread, 656 int flavor, 657 thread_state_t tstate, 658 mach_msg_type_number_t *count) 659{ 660 return (thread_get_state(thread, flavor, tstate, count)); 661} 662 663/* 664 * install_special_handler: 665 * 666 * Install the special returnhandler that handles suspension and 667 * termination, if it hasn't been installed already. 668 * 669 * Called with the thread mutex held. 670 */ 671void 672install_special_handler( 673 thread_t thread) 674{ 675 spl_t s = splsched(); 676 677 thread_lock(thread); 678 install_special_handler_locked(thread); 679 thread_unlock(thread); 680 splx(s); 681} 682 683/* 684 * install_special_handler_locked: 685 * 686 * Do the work of installing the special_handler. 687 * 688 * Called with the thread mutex and scheduling lock held. 689 */ 690void 691install_special_handler_locked( 692 thread_t thread) 693{ 694 ReturnHandler **rh; 695 696 /* The work handler must always be the last ReturnHandler on the list, 697 because it can do tricky things like detach the thr_act. */ 698 for (rh = &thread->handlers; *rh; rh = &(*rh)->next) 699 continue; 700 701 if (rh != &thread->special_handler.next) 702 *rh = &thread->special_handler; 703 704 /* 705 * Temporarily undepress, so target has 706 * a chance to do locking required to 707 * block itself in special_handler(). 708 */ 709 if (thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) 710 SCHED(compute_priority)(thread, TRUE); 711 712 thread_ast_set(thread, AST_APC); 713 714 if (thread == current_thread()) 715 ast_propagate(thread->ast); 716 else { 717 processor_t processor = thread->last_processor; 718 719 if ( processor != PROCESSOR_NULL && 720 processor->state == PROCESSOR_RUNNING && 721 processor->active_thread == thread ) 722 cause_ast_check(processor); 723 } 724} 725 726/* 727 * Activation control support routines internal to this file: 728 */ 729 730void 731act_execute_returnhandlers(void) 732{ 733 thread_t thread = current_thread(); 734 735 thread_ast_clear(thread, AST_APC); 736 spllo(); 737 738 for (;;) { 739 ReturnHandler *rh; 740 741 thread_mtx_lock(thread); 742 743 (void)splsched(); 744 thread_lock(thread); 745 746 rh = thread->handlers; 747 if (rh != NULL) { 748 thread->handlers = rh->next; 749 750 thread_unlock(thread); 751 spllo(); 752 753 thread_mtx_unlock(thread); 754 755 /* Execute it */ 756 (*rh->handler)(rh, thread); 757 } 758 else 759 break; 760 } 761 762 thread_unlock(thread); 763 spllo(); 764 765 thread_mtx_unlock(thread); 766} 767 768/* 769 * special_handler_continue 770 * 771 * Continuation routine for the special handler blocks. It checks 772 * to see whether there has been any new suspensions. If so, it 773 * installs the special handler again. Otherwise, it checks to see 774 * if the current depression needs to be re-instated (it may have 775 * been temporarily removed in order to get to this point in a hurry). 776 */ 777void 778special_handler_continue(void) 779{ 780 thread_t thread = current_thread(); 781 782 thread_mtx_lock(thread); 783 784 if (thread->suspend_count > 0) 785 install_special_handler(thread); 786 else { 787 spl_t s = splsched(); 788 789 thread_lock(thread); 790 if (thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) { 791 processor_t myprocessor = thread->last_processor; 792 793 thread->sched_pri = DEPRESSPRI; 794 myprocessor->current_pri = thread->sched_pri; 795 } 796 thread_unlock(thread); 797 splx(s); 798 } 799 800 thread_mtx_unlock(thread); 801 802 thread_exception_return(); 803 /*NOTREACHED*/ 804} 805 806/* 807 * special_handler - handles suspension, termination. Called 808 * with nothing locked. Returns (if it returns) the same way. 809 */ 810void 811special_handler( 812 __unused ReturnHandler *rh, 813 thread_t thread) 814{ 815 spl_t s; 816 817 thread_mtx_lock(thread); 818 819 s = splsched(); 820 thread_lock(thread); 821 thread->sched_flags &= ~TH_SFLAG_ABORTED_MASK; 822 thread_unlock(thread); 823 splx(s); 824 825 /* 826 * If we're suspended, go to sleep and wait for someone to wake us up. 827 */ 828 if (thread->active) { 829 if (thread->suspend_count > 0) { 830 if (thread->handlers == NULL) { 831 assert_wait(&thread->suspend_count, THREAD_ABORTSAFE); 832 thread_mtx_unlock(thread); 833 thread_block((thread_continue_t)special_handler_continue); 834 /*NOTREACHED*/ 835 } 836 837 thread_mtx_unlock(thread); 838 839 special_handler_continue(); 840 /*NOTREACHED*/ 841 } 842 } 843 else { 844 thread_mtx_unlock(thread); 845 846 thread_terminate_self(); 847 /*NOTREACHED*/ 848 } 849 850 thread_mtx_unlock(thread); 851} 852 853/* Prototype, see justification above */ 854kern_return_t 855act_set_state( 856 thread_t thread, 857 int flavor, 858 thread_state_t state, 859 mach_msg_type_number_t count); 860 861kern_return_t 862act_set_state( 863 thread_t thread, 864 int flavor, 865 thread_state_t state, 866 mach_msg_type_number_t count) 867{ 868 if (thread == current_thread()) 869 return (KERN_INVALID_ARGUMENT); 870 871 return (thread_set_state(thread, flavor, state, count)); 872 873} 874 875kern_return_t 876act_set_state_from_user( 877 thread_t thread, 878 int flavor, 879 thread_state_t state, 880 mach_msg_type_number_t count) 881{ 882 if (thread == current_thread()) 883 return (KERN_INVALID_ARGUMENT); 884 885 return (thread_set_state_from_user(thread, flavor, state, count)); 886 887} 888 889kern_return_t 890act_get_state( 891 thread_t thread, 892 int flavor, 893 thread_state_t state, 894 mach_msg_type_number_t *count) 895{ 896 if (thread == current_thread()) 897 return (KERN_INVALID_ARGUMENT); 898 899 return (thread_get_state(thread, flavor, state, count)); 900} 901 902static void 903act_set_ast( 904 thread_t thread, 905 ast_t ast) 906{ 907 spl_t s = splsched(); 908 909 if (thread == current_thread()) { 910 thread_ast_set(thread, ast); 911 ast_propagate(thread->ast); 912 } 913 else { 914 processor_t processor; 915 916 thread_lock(thread); 917 thread_ast_set(thread, ast); 918 processor = thread->last_processor; 919 if ( processor != PROCESSOR_NULL && 920 processor->state == PROCESSOR_RUNNING && 921 processor->active_thread == thread ) 922 cause_ast_check(processor); 923 thread_unlock(thread); 924 } 925 926 splx(s); 927} 928 929void 930act_set_astbsd( 931 thread_t thread) 932{ 933 act_set_ast( thread, AST_BSD ); 934} 935 936void 937act_set_apc( 938 thread_t thread) 939{ 940 act_set_ast( thread, AST_APC ); 941} 942 943void 944act_set_kperf( 945 thread_t thread) 946{ 947 /* safety check */ 948 if (thread != current_thread()) 949 if( !ml_get_interrupts_enabled() ) 950 panic("unsafe act_set_kperf operation"); 951 952 act_set_ast( thread, AST_KPERF ); 953} 954 955#if CONFIG_MACF 956void 957act_set_astmacf( 958 thread_t thread) 959{ 960 act_set_ast( thread, AST_MACF); 961} 962#endif 963