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/thread.h>
63 #include <kern/task.h>
64 #include <kern/sched_prim.h>
65 #include <kern/misc_protos.h>
66 #include <kern/assert.h>
67 #include <kern/exception.h>
68 #include <kern/ipc_mig.h>
69 #include <kern/ipc_tt.h>
70 #include <kern/machine.h>
72 #include <kern/syscall_subr.h>
73 #include <kern/sync_lock.h>
74 #include <kern/processor.h>
75 #include <kern/timer.h>
76 #include <kern/affinity.h>
82 void act_abort(thread_t
);
83 void install_special_handler_locked(thread_t
);
84 void special_handler_continue(void);
87 * Internal routine to mark a thread as started.
88 * Always called with the thread locked.
90 * Note: function intentionall declared with the noinline attribute to
91 * prevent multiple declaration of probe symbols in this file; we would
92 * prefer "#pragma noinline", but gcc does not support it.
95 thread_start_internal(
98 clear_wait(thread
, THREAD_AWAKENED
);
99 thread
->started
= TRUE
;
100 DTRACE_PROC1(lwp__start
, thread_t
, thread
);
104 * Internal routine to terminate a thread.
105 * Sometimes called with task already locked.
108 thread_terminate_internal(
111 kern_return_t result
= KERN_SUCCESS
;
113 DTRACE_PROC(lwp__exit
);
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_mode
& TH_MODE_ABORT
)) {
319 thread
->sched_mode
|= TH_MODE_ABORT
;
320 install_special_handler_locked(thread
);
323 thread
->sched_mode
&= ~TH_MODE_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_mode
& TH_MODE_ABORT
)) {
370 thread
->sched_mode
|= TH_MODE_ISABORTED
;
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.
466 register thread_t thread
,
468 thread_state_t state
,
469 mach_msg_type_number_t state_count
)
471 kern_return_t result
= KERN_SUCCESS
;
473 if (thread
== THREAD_NULL
)
474 return (KERN_INVALID_ARGUMENT
);
476 thread_mtx_lock(thread
);
478 if (thread
->active
) {
479 if (thread
!= current_thread()) {
482 thread_mtx_unlock(thread
);
484 if (thread_stop(thread
)) {
485 thread_mtx_lock(thread
);
486 result
= machine_thread_set_state(
487 thread
, flavor
, state
, state_count
);
488 thread_unstop(thread
);
491 thread_mtx_lock(thread
);
492 result
= KERN_ABORTED
;
495 thread_release(thread
);
498 result
= machine_thread_set_state(
499 thread
, flavor
, state
, state_count
);
502 result
= KERN_TERMINATED
;
504 thread_mtx_unlock(thread
);
511 * Kernel-internal "thread" interfaces used outside this file:
514 /* Initialize (or re-initialize) a thread state. Called from execve
515 * with nothing locked, returns same way.
518 thread_state_initialize(
519 register thread_t thread
)
521 kern_return_t result
= KERN_SUCCESS
;
523 if (thread
== THREAD_NULL
)
524 return (KERN_INVALID_ARGUMENT
);
526 thread_mtx_lock(thread
);
528 if (thread
->active
) {
529 if (thread
!= current_thread()) {
532 thread_mtx_unlock(thread
);
534 if (thread_stop(thread
)) {
535 thread_mtx_lock(thread
);
536 result
= machine_thread_state_initialize( thread
);
537 thread_unstop(thread
);
540 thread_mtx_lock(thread
);
541 result
= KERN_ABORTED
;
544 thread_release(thread
);
547 result
= machine_thread_state_initialize( thread
);
550 result
= KERN_TERMINATED
;
552 thread_mtx_unlock(thread
);
560 register thread_t target
)
562 thread_t self
= current_thread();
563 kern_return_t result
= KERN_SUCCESS
;
565 if (target
== THREAD_NULL
|| target
== self
)
566 return (KERN_INVALID_ARGUMENT
);
568 thread_mtx_lock(target
);
570 if (target
->active
) {
573 thread_mtx_unlock(target
);
575 if (thread_stop(target
)) {
576 thread_mtx_lock(target
);
577 result
= machine_thread_dup(self
, target
);
578 if (self
->affinity_set
!= AFFINITY_SET_NULL
)
579 thread_affinity_dup(self
, target
);
580 thread_unstop(target
);
583 thread_mtx_lock(target
);
584 result
= KERN_ABORTED
;
587 thread_release(target
);
590 result
= KERN_TERMINATED
;
592 thread_mtx_unlock(target
);
601 * Set the status of the specified thread.
602 * Called with (and returns with) no locks held.
606 register thread_t thread
,
608 thread_state_t tstate
,
609 mach_msg_type_number_t count
)
612 return (thread_set_state(thread
, flavor
, tstate
, count
));
618 * Get the status of the specified thread.
622 register thread_t thread
,
624 thread_state_t tstate
,
625 mach_msg_type_number_t
*count
)
627 return (thread_get_state(thread
, flavor
, tstate
, count
));
631 * install_special_handler:
633 * Install the special returnhandler that handles suspension and
634 * termination, if it hasn't been installed already.
636 * Called with the thread mutex held.
639 install_special_handler(
642 spl_t s
= splsched();
645 install_special_handler_locked(thread
);
646 thread_unlock(thread
);
651 * install_special_handler_locked:
653 * Do the work of installing the special_handler.
655 * Called with the thread mutex and scheduling lock held.
658 install_special_handler_locked(
663 /* The work handler must always be the last ReturnHandler on the list,
664 because it can do tricky things like detach the thr_act. */
665 for (rh
= &thread
->handlers
; *rh
; rh
= &(*rh
)->next
)
668 if (rh
!= &thread
->special_handler
.next
)
669 *rh
= &thread
->special_handler
;
672 * Temporarily undepress, so target has
673 * a chance to do locking required to
674 * block itself in special_handler().
676 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
)
677 compute_priority(thread
, TRUE
);
679 thread_ast_set(thread
, AST_APC
);
681 if (thread
== current_thread())
682 ast_propagate(thread
->ast
);
684 processor_t processor
= thread
->last_processor
;
686 if ( processor
!= PROCESSOR_NULL
&&
687 processor
->state
== PROCESSOR_RUNNING
&&
688 processor
->active_thread
== thread
)
689 cause_ast_check(processor
);
694 * Activation control support routines internal to this file:
698 act_execute_returnhandlers(void)
700 thread_t thread
= current_thread();
702 thread_ast_clear(thread
, AST_APC
);
708 thread_mtx_lock(thread
);
713 rh
= thread
->handlers
;
715 thread
->handlers
= rh
->next
;
717 thread_unlock(thread
);
720 thread_mtx_unlock(thread
);
723 (*rh
->handler
)(rh
, thread
);
729 thread_unlock(thread
);
732 thread_mtx_unlock(thread
);
736 * special_handler_continue
738 * Continuation routine for the special handler blocks. It checks
739 * to see whether there has been any new suspensions. If so, it
740 * installs the special handler again. Otherwise, it checks to see
741 * if the current depression needs to be re-instated (it may have
742 * been temporarily removed in order to get to this point in a hurry).
745 special_handler_continue(void)
747 thread_t thread
= current_thread();
749 thread_mtx_lock(thread
);
751 if (thread
->suspend_count
> 0)
752 install_special_handler(thread
);
754 spl_t s
= splsched();
757 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
758 processor_t myprocessor
= thread
->last_processor
;
760 thread
->sched_pri
= DEPRESSPRI
;
761 myprocessor
->current_pri
= thread
->sched_pri
;
763 thread_unlock(thread
);
767 thread_mtx_unlock(thread
);
769 thread_exception_return();
774 * special_handler - handles suspension, termination. Called
775 * with nothing locked. Returns (if it returns) the same way.
779 __unused ReturnHandler
*rh
,
784 thread_mtx_lock(thread
);
788 thread
->sched_mode
&= ~TH_MODE_ISABORTED
;
789 thread_unlock(thread
);
793 * If we're suspended, go to sleep and wait for someone to wake us up.
795 if (thread
->active
) {
796 if (thread
->suspend_count
> 0) {
797 if (thread
->handlers
== NULL
) {
798 assert_wait(&thread
->suspend_count
, THREAD_ABORTSAFE
);
799 thread_mtx_unlock(thread
);
800 thread_block((thread_continue_t
)special_handler_continue
);
804 thread_mtx_unlock(thread
);
806 special_handler_continue();
811 thread_mtx_unlock(thread
);
813 thread_terminate_self();
817 thread_mtx_unlock(thread
);
824 thread_state_t state
,
825 mach_msg_type_number_t count
)
827 if (thread
== current_thread())
828 return (KERN_INVALID_ARGUMENT
);
830 return (thread_set_state(thread
, flavor
, state
, count
));
838 thread_state_t state
,
839 mach_msg_type_number_t
*count
)
841 if (thread
== current_thread())
842 return (KERN_INVALID_ARGUMENT
);
844 return (thread_get_state(thread
, flavor
, state
, count
));
851 spl_t s
= splsched();
853 if (thread
== current_thread()) {
854 thread_ast_set(thread
, AST_BSD
);
855 ast_propagate(thread
->ast
);
858 processor_t processor
;
861 thread_ast_set(thread
, AST_BSD
);
862 processor
= thread
->last_processor
;
863 if ( processor
!= PROCESSOR_NULL
&&
864 processor
->state
== PROCESSOR_RUNNING
&&
865 processor
->active_thread
== thread
)
866 cause_ast_check(processor
);
867 thread_unlock(thread
);
877 spl_t s
= splsched();
879 if (thread
== current_thread()) {
880 thread_ast_set(thread
, AST_APC
);
881 ast_propagate(thread
->ast
);
884 processor_t processor
;
887 thread_ast_set(thread
, AST_APC
);
888 processor
= thread
->last_processor
;
889 if ( processor
!= PROCESSOR_NULL
&&
890 processor
->state
== PROCESSOR_RUNNING
&&
891 processor
->active_thread
== thread
)
892 cause_ast_check(processor
);
893 thread_unlock(thread
);