2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * @OSF_FREE_COPYRIGHT@
32 * Copyright (c) 1993 The University of Utah and
33 * the Center for Software Science (CSS). All rights reserved.
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.
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.
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.
48 * Author: Bryan Ford, University of Utah CSS
50 * Thread management routines
52 #include <mach/mach_types.h>
53 #include <mach/kern_return.h>
54 #include <mach/alert.h>
56 #include <mach/thread_act_server.h>
58 #include <kern/kern_types.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>
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>
81 void act_abort(thread_t
);
82 void install_special_handler_locked(thread_t
);
83 void special_handler_continue(void);
86 * Internal routine to mark a thread as started.
87 * Always called with the thread locked.
89 * Note: function intentionally declared with the noinline attribute to
90 * prevent multiple declaration of probe symbols in this file; we would
91 * prefer "#pragma noinline", but gcc does not support it.
92 * PR-6385749 -- the lwp-start probe should fire from within the context
93 * of the newly created thread. Commented out for now, in case we
94 * turn it into a dead code probe.
97 thread_start_internal(
100 clear_wait(thread
, THREAD_AWAKENED
);
101 thread
->started
= TRUE
;
102 // DTRACE_PROC1(lwp__start, thread_t, thread);
106 * Internal routine to terminate a thread.
107 * Sometimes called with task already locked.
110 thread_terminate_internal(
113 kern_return_t result
= KERN_SUCCESS
;
115 thread_mtx_lock(thread
);
117 if (thread
->active
) {
118 thread
->active
= FALSE
;
123 clear_wait(thread
, THREAD_INTERRUPTED
);
125 thread_start_internal(thread
);
129 result
= KERN_TERMINATED
;
131 if (thread
->affinity_set
!= NULL
)
132 thread_affinity_terminate(thread
);
134 thread_mtx_unlock(thread
);
136 if (thread
!= current_thread() && result
== KERN_SUCCESS
)
143 * Terminate a thread.
149 kern_return_t result
;
151 if (thread
== THREAD_NULL
)
152 return (KERN_INVALID_ARGUMENT
);
154 if ( thread
->task
== kernel_task
&&
155 thread
!= current_thread() )
156 return (KERN_FAILURE
);
158 result
= thread_terminate_internal(thread
);
161 * If a kernel thread is terminating itself, force an AST here.
162 * Kernel threads don't normally pass through the AST checking
163 * code - and all threads finish their own termination in the
164 * special handler APC.
166 if (thread
->task
== kernel_task
) {
167 ml_set_interrupts_enabled(FALSE
);
168 ast_taken(AST_APC
, TRUE
);
169 panic("thread_terminate");
176 * Suspend execution of the specified thread.
177 * This is a recursive-style suspension of the thread, a count of
178 * suspends is maintained.
180 * Called with thread mutex held.
184 register thread_t thread
)
186 if (thread
->suspend_count
++ == 0) {
187 install_special_handler(thread
);
189 thread_wakeup_one(&thread
->suspend_count
);
194 * Decrement internal suspension count, setting thread
195 * runnable when count falls to zero.
197 * Called with thread mutex held.
201 register thread_t thread
)
203 if ( thread
->suspend_count
> 0 &&
204 --thread
->suspend_count
== 0 ) {
206 thread_wakeup_one(&thread
->suspend_count
);
208 thread_start_internal(thread
);
215 register thread_t thread
)
217 thread_t self
= current_thread();
218 kern_return_t result
= KERN_SUCCESS
;
220 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
221 return (KERN_INVALID_ARGUMENT
);
223 thread_mtx_lock(thread
);
225 if (thread
->active
) {
226 if ( thread
->user_stop_count
++ == 0 &&
227 thread
->suspend_count
++ == 0 ) {
228 install_special_handler(thread
);
230 thread_wakeup_one(&thread
->suspend_count
);
234 result
= KERN_TERMINATED
;
236 thread_mtx_unlock(thread
);
238 if (thread
!= self
&& result
== KERN_SUCCESS
)
246 register thread_t thread
)
248 kern_return_t result
= KERN_SUCCESS
;
250 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
251 return (KERN_INVALID_ARGUMENT
);
253 thread_mtx_lock(thread
);
255 if (thread
->active
) {
256 if (thread
->user_stop_count
> 0) {
257 if ( --thread
->user_stop_count
== 0 &&
258 --thread
->suspend_count
== 0 ) {
260 thread_wakeup_one(&thread
->suspend_count
);
262 thread_start_internal(thread
);
267 result
= KERN_FAILURE
;
270 result
= KERN_TERMINATED
;
272 thread_mtx_unlock(thread
);
278 * thread_depress_abort:
280 * Prematurely abort priority depression if there is one.
283 thread_depress_abort(
284 register thread_t thread
)
286 kern_return_t result
;
288 if (thread
== THREAD_NULL
)
289 return (KERN_INVALID_ARGUMENT
);
291 thread_mtx_lock(thread
);
294 result
= thread_depress_abort_internal(thread
);
296 result
= KERN_TERMINATED
;
298 thread_mtx_unlock(thread
);
305 * Indicate that the activation should run its
306 * special handler to detect a condition.
308 * Called with thread mutex held.
314 spl_t s
= splsched();
318 if (!(thread
->sched_flags
& TH_SFLAG_ABORT
)) {
319 thread
->sched_flags
|= TH_SFLAG_ABORT
;
320 install_special_handler_locked(thread
);
323 thread
->sched_flags
&= ~TH_SFLAG_ABORTSAFELY
;
325 thread_unlock(thread
);
331 register thread_t thread
)
333 kern_return_t result
= KERN_SUCCESS
;
335 if (thread
== THREAD_NULL
)
336 return (KERN_INVALID_ARGUMENT
);
338 thread_mtx_lock(thread
);
340 if (thread
->active
) {
342 clear_wait(thread
, THREAD_INTERRUPTED
);
345 result
= KERN_TERMINATED
;
347 thread_mtx_unlock(thread
);
356 kern_return_t result
= KERN_SUCCESS
;
358 if (thread
== THREAD_NULL
)
359 return (KERN_INVALID_ARGUMENT
);
361 thread_mtx_lock(thread
);
363 if (thread
->active
) {
364 spl_t s
= splsched();
367 if (!thread
->at_safe_point
||
368 clear_wait_internal(thread
, THREAD_INTERRUPTED
) != KERN_SUCCESS
) {
369 if (!(thread
->sched_flags
& TH_SFLAG_ABORT
)) {
370 thread
->sched_flags
|= TH_SFLAG_ABORTED_MASK
;
371 install_special_handler_locked(thread
);
374 thread_unlock(thread
);
378 result
= KERN_TERMINATED
;
380 thread_mtx_unlock(thread
);
385 /*** backward compatibility hacks ***/
386 #include <mach/thread_info.h>
387 #include <mach/thread_special_ports.h>
388 #include <ipc/ipc_port.h>
393 thread_flavor_t flavor
,
394 thread_info_t thread_info_out
,
395 mach_msg_type_number_t
*thread_info_count
)
397 kern_return_t result
;
399 if (thread
== THREAD_NULL
)
400 return (KERN_INVALID_ARGUMENT
);
402 thread_mtx_lock(thread
);
405 result
= thread_info_internal(
406 thread
, flavor
, thread_info_out
, thread_info_count
);
408 result
= KERN_TERMINATED
;
410 thread_mtx_unlock(thread
);
417 register thread_t thread
,
419 thread_state_t state
, /* pointer to OUT array */
420 mach_msg_type_number_t
*state_count
) /*IN/OUT*/
422 kern_return_t result
= KERN_SUCCESS
;
424 if (thread
== THREAD_NULL
)
425 return (KERN_INVALID_ARGUMENT
);
427 thread_mtx_lock(thread
);
429 if (thread
->active
) {
430 if (thread
!= current_thread()) {
433 thread_mtx_unlock(thread
);
435 if (thread_stop(thread
)) {
436 thread_mtx_lock(thread
);
437 result
= machine_thread_get_state(
438 thread
, flavor
, state
, state_count
);
439 thread_unstop(thread
);
442 thread_mtx_lock(thread
);
443 result
= KERN_ABORTED
;
446 thread_release(thread
);
449 result
= machine_thread_get_state(
450 thread
, flavor
, state
, state_count
);
453 result
= KERN_TERMINATED
;
455 thread_mtx_unlock(thread
);
461 * Change thread's machine-dependent state. Called with nothing
462 * locked. Returns same way.
465 thread_set_state_internal(
466 register thread_t thread
,
468 thread_state_t state
,
469 mach_msg_type_number_t state_count
,
472 kern_return_t result
= KERN_SUCCESS
;
474 if (thread
== THREAD_NULL
)
475 return (KERN_INVALID_ARGUMENT
);
477 thread_mtx_lock(thread
);
479 if (thread
->active
) {
480 if (thread
!= current_thread()) {
483 thread_mtx_unlock(thread
);
485 if (thread_stop(thread
)) {
486 thread_mtx_lock(thread
);
487 result
= machine_thread_set_state(
488 thread
, flavor
, state
, state_count
);
489 thread_unstop(thread
);
492 thread_mtx_lock(thread
);
493 result
= KERN_ABORTED
;
496 thread_release(thread
);
499 result
= machine_thread_set_state(
500 thread
, flavor
, state
, state_count
);
503 result
= KERN_TERMINATED
;
505 if ((result
== KERN_SUCCESS
) && from_user
)
506 extmod_statistics_incr_thread_set_state(thread
);
508 thread_mtx_unlock(thread
);
513 /* No prototype, since thread_act_server.h has the _from_user version if KERNEL_SERVER */
516 register thread_t thread
,
518 thread_state_t state
,
519 mach_msg_type_number_t state_count
);
523 register thread_t thread
,
525 thread_state_t state
,
526 mach_msg_type_number_t state_count
)
528 return thread_set_state_internal(thread
, flavor
, state
, state_count
, FALSE
);
532 thread_set_state_from_user(
533 register thread_t thread
,
535 thread_state_t state
,
536 mach_msg_type_number_t state_count
)
538 return thread_set_state_internal(thread
, flavor
, state
, state_count
, TRUE
);
542 * Kernel-internal "thread" interfaces used outside this file:
545 /* Initialize (or re-initialize) a thread state. Called from execve
546 * with nothing locked, returns same way.
549 thread_state_initialize(
550 register thread_t thread
)
552 kern_return_t result
= KERN_SUCCESS
;
554 if (thread
== THREAD_NULL
)
555 return (KERN_INVALID_ARGUMENT
);
557 thread_mtx_lock(thread
);
559 if (thread
->active
) {
560 if (thread
!= current_thread()) {
563 thread_mtx_unlock(thread
);
565 if (thread_stop(thread
)) {
566 thread_mtx_lock(thread
);
567 result
= machine_thread_state_initialize( thread
);
568 thread_unstop(thread
);
571 thread_mtx_lock(thread
);
572 result
= KERN_ABORTED
;
575 thread_release(thread
);
578 result
= machine_thread_state_initialize( thread
);
581 result
= KERN_TERMINATED
;
583 thread_mtx_unlock(thread
);
591 register thread_t target
)
593 thread_t self
= current_thread();
594 kern_return_t result
= KERN_SUCCESS
;
596 if (target
== THREAD_NULL
|| target
== self
)
597 return (KERN_INVALID_ARGUMENT
);
599 thread_mtx_lock(target
);
601 if (target
->active
) {
604 thread_mtx_unlock(target
);
606 if (thread_stop(target
)) {
607 thread_mtx_lock(target
);
608 result
= machine_thread_dup(self
, target
);
609 if (self
->affinity_set
!= AFFINITY_SET_NULL
)
610 thread_affinity_dup(self
, target
);
611 thread_unstop(target
);
614 thread_mtx_lock(target
);
615 result
= KERN_ABORTED
;
618 thread_release(target
);
621 result
= KERN_TERMINATED
;
623 thread_mtx_unlock(target
);
632 * Set the status of the specified thread.
633 * Called with (and returns with) no locks held.
637 register thread_t thread
,
639 thread_state_t tstate
,
640 mach_msg_type_number_t count
)
643 return (thread_set_state(thread
, flavor
, tstate
, count
));
649 * Get the status of the specified thread.
653 register thread_t thread
,
655 thread_state_t tstate
,
656 mach_msg_type_number_t
*count
)
658 return (thread_get_state(thread
, flavor
, tstate
, count
));
662 * install_special_handler:
664 * Install the special returnhandler that handles suspension and
665 * termination, if it hasn't been installed already.
667 * Called with the thread mutex held.
670 install_special_handler(
673 spl_t s
= splsched();
676 install_special_handler_locked(thread
);
677 thread_unlock(thread
);
682 * install_special_handler_locked:
684 * Do the work of installing the special_handler.
686 * Called with the thread mutex and scheduling lock held.
689 install_special_handler_locked(
694 /* The work handler must always be the last ReturnHandler on the list,
695 because it can do tricky things like detach the thr_act. */
696 for (rh
= &thread
->handlers
; *rh
; rh
= &(*rh
)->next
)
699 if (rh
!= &thread
->special_handler
.next
)
700 *rh
= &thread
->special_handler
;
703 * Temporarily undepress, so target has
704 * a chance to do locking required to
705 * block itself in special_handler().
707 if (thread
->sched_flags
& TH_SFLAG_DEPRESSED_MASK
)
708 SCHED(compute_priority
)(thread
, TRUE
);
710 thread_ast_set(thread
, AST_APC
);
712 if (thread
== current_thread())
713 ast_propagate(thread
->ast
);
715 processor_t processor
= thread
->last_processor
;
717 if ( processor
!= PROCESSOR_NULL
&&
718 processor
->state
== PROCESSOR_RUNNING
&&
719 processor
->active_thread
== thread
)
720 cause_ast_check(processor
);
725 * Activation control support routines internal to this file:
729 act_execute_returnhandlers(void)
731 thread_t thread
= current_thread();
733 thread_ast_clear(thread
, AST_APC
);
739 thread_mtx_lock(thread
);
744 rh
= thread
->handlers
;
746 thread
->handlers
= rh
->next
;
748 thread_unlock(thread
);
751 thread_mtx_unlock(thread
);
754 (*rh
->handler
)(rh
, thread
);
760 thread_unlock(thread
);
763 thread_mtx_unlock(thread
);
767 * special_handler_continue
769 * Continuation routine for the special handler blocks. It checks
770 * to see whether there has been any new suspensions. If so, it
771 * installs the special handler again. Otherwise, it checks to see
772 * if the current depression needs to be re-instated (it may have
773 * been temporarily removed in order to get to this point in a hurry).
776 special_handler_continue(void)
778 thread_t thread
= current_thread();
780 thread_mtx_lock(thread
);
782 if (thread
->suspend_count
> 0)
783 install_special_handler(thread
);
785 spl_t s
= splsched();
788 if (thread
->sched_flags
& TH_SFLAG_DEPRESSED_MASK
) {
789 processor_t myprocessor
= thread
->last_processor
;
791 thread
->sched_pri
= DEPRESSPRI
;
792 myprocessor
->current_pri
= thread
->sched_pri
;
794 thread_unlock(thread
);
798 thread_mtx_unlock(thread
);
800 thread_exception_return();
805 * special_handler - handles suspension, termination. Called
806 * with nothing locked. Returns (if it returns) the same way.
810 __unused ReturnHandler
*rh
,
815 thread_mtx_lock(thread
);
819 thread
->sched_flags
&= ~TH_SFLAG_ABORTED_MASK
;
820 thread_unlock(thread
);
824 * If we're suspended, go to sleep and wait for someone to wake us up.
826 if (thread
->active
) {
827 if (thread
->suspend_count
> 0) {
828 if (thread
->handlers
== NULL
) {
829 assert_wait(&thread
->suspend_count
, THREAD_ABORTSAFE
);
830 thread_mtx_unlock(thread
);
831 thread_block((thread_continue_t
)special_handler_continue
);
835 thread_mtx_unlock(thread
);
837 special_handler_continue();
842 thread_mtx_unlock(thread
);
844 thread_terminate_self();
848 thread_mtx_unlock(thread
);
851 /* Prototype, see justification above */
856 thread_state_t state
,
857 mach_msg_type_number_t count
);
863 thread_state_t state
,
864 mach_msg_type_number_t count
)
866 if (thread
== current_thread())
867 return (KERN_INVALID_ARGUMENT
);
869 return (thread_set_state(thread
, flavor
, state
, count
));
874 act_set_state_from_user(
877 thread_state_t state
,
878 mach_msg_type_number_t count
)
880 if (thread
== current_thread())
881 return (KERN_INVALID_ARGUMENT
);
883 return (thread_set_state_from_user(thread
, flavor
, state
, count
));
891 thread_state_t state
,
892 mach_msg_type_number_t
*count
)
894 if (thread
== current_thread())
895 return (KERN_INVALID_ARGUMENT
);
897 return (thread_get_state(thread
, flavor
, state
, count
));
904 spl_t s
= splsched();
906 if (thread
== current_thread()) {
907 thread_ast_set(thread
, AST_BSD
);
908 ast_propagate(thread
->ast
);
911 processor_t processor
;
914 thread_ast_set(thread
, AST_BSD
);
915 processor
= thread
->last_processor
;
916 if ( processor
!= PROCESSOR_NULL
&&
917 processor
->state
== PROCESSOR_RUNNING
&&
918 processor
->active_thread
== thread
)
919 cause_ast_check(processor
);
920 thread_unlock(thread
);
930 spl_t s
= splsched();
932 if (thread
== current_thread()) {
933 thread_ast_set(thread
, AST_APC
);
934 ast_propagate(thread
->ast
);
937 processor_t processor
;
940 thread_ast_set(thread
, AST_APC
);
941 processor
= thread
->last_processor
;
942 if ( processor
!= PROCESSOR_NULL
&&
943 processor
->state
== PROCESSOR_RUNNING
&&
944 processor
->active_thread
== thread
)
945 cause_ast_check(processor
);
946 thread_unlock(thread
);