2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
21 * @APPLE_LICENSE_HEADER_END@
24 * @OSF_FREE_COPYRIGHT@
27 * Copyright (c) 1993 The University of Utah and
28 * the Center for Software Science (CSS). All rights reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
37 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
38 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * CSS requests users of this software to return to css-dist@cs.utah.edu any
41 * improvements that they make and grant CSS redistribution rights.
43 * Author: Bryan Ford, University of Utah CSS
45 * Thread management routines
47 #include <mach/mach_types.h>
48 #include <mach/kern_return.h>
49 #include <mach/alert.h>
50 #include <mach_prof.h>
52 #include <mach/thread_act_server.h>
54 #include <kern/kern_types.h>
56 #include <kern/mach_param.h>
57 #include <kern/zalloc.h>
58 #include <kern/thread.h>
59 #include <kern/task.h>
60 #include <kern/sched_prim.h>
61 #include <kern/misc_protos.h>
62 #include <kern/assert.h>
63 #include <kern/exception.h>
64 #include <kern/ipc_mig.h>
65 #include <kern/ipc_tt.h>
66 #include <kern/profile.h>
67 #include <kern/machine.h>
69 #include <kern/syscall_subr.h>
70 #include <kern/sync_lock.h>
71 #include <kern/processor.h>
72 #include <kern/timer.h>
73 #include <mach_prof.h>
76 void act_abort(thread_t
);
77 void act_set_apc(thread_t
);
78 void install_special_handler_locked(thread_t
);
79 void special_handler_continue(void);
82 * Internal routine to terminate a thread.
83 * Sometimes called with task already locked.
86 thread_terminate_internal(
89 kern_return_t result
= KERN_SUCCESS
;
91 thread_mtx_lock(thread
);
94 thread
->active
= FALSE
;
99 clear_wait(thread
, THREAD_INTERRUPTED
);
101 clear_wait(thread
, THREAD_AWAKENED
);
102 thread
->started
= TRUE
;
106 result
= KERN_TERMINATED
;
108 thread_mtx_unlock(thread
);
110 if (thread
!= current_thread() && result
== KERN_SUCCESS
)
117 * Terminate a thread.
123 kern_return_t result
;
125 if (thread
== THREAD_NULL
)
126 return (KERN_INVALID_ARGUMENT
);
128 if ( thread
->task
== kernel_task
&&
129 thread
!= current_thread() )
130 return (KERN_FAILURE
);
132 result
= thread_terminate_internal(thread
);
135 * If a kernel thread is terminating itself, force an AST here.
136 * Kernel threads don't normally pass through the AST checking
137 * code - and all threads finish their own termination in the
138 * special handler APC.
140 if (thread
->task
== kernel_task
) {
141 ml_set_interrupts_enabled(FALSE
);
142 ast_taken(AST_APC
, TRUE
);
143 panic("thread_terminate");
150 * Suspend execution of the specified thread.
151 * This is a recursive-style suspension of the thread, a count of
152 * suspends is maintained.
154 * Called with thread mutex held.
158 register thread_t thread
)
160 if (thread
->suspend_count
++ == 0) {
161 install_special_handler(thread
);
163 thread_wakeup_one(&thread
->suspend_count
);
168 * Decrement internal suspension count, setting thread
169 * runnable when count falls to zero.
171 * Called with thread mutex held.
175 register thread_t thread
)
177 if ( thread
->suspend_count
> 0 &&
178 --thread
->suspend_count
== 0 ) {
180 thread_wakeup_one(&thread
->suspend_count
);
182 clear_wait(thread
, THREAD_AWAKENED
);
183 thread
->started
= TRUE
;
190 register thread_t thread
)
192 thread_t self
= current_thread();
193 kern_return_t result
= KERN_SUCCESS
;
195 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
196 return (KERN_INVALID_ARGUMENT
);
198 thread_mtx_lock(thread
);
200 if (thread
->active
) {
201 if ( thread
->user_stop_count
++ == 0 &&
202 thread
->suspend_count
++ == 0 ) {
203 install_special_handler(thread
);
205 thread_wakeup_one(&thread
->suspend_count
);
209 result
= KERN_TERMINATED
;
211 thread_mtx_unlock(thread
);
213 if (thread
!= self
&& result
== KERN_SUCCESS
)
221 register thread_t thread
)
223 kern_return_t result
= KERN_SUCCESS
;
225 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
226 return (KERN_INVALID_ARGUMENT
);
228 thread_mtx_lock(thread
);
230 if (thread
->active
) {
231 if (thread
->user_stop_count
> 0) {
232 if ( --thread
->user_stop_count
== 0 &&
233 --thread
->suspend_count
== 0 ) {
235 thread_wakeup_one(&thread
->suspend_count
);
237 clear_wait(thread
, THREAD_AWAKENED
);
238 thread
->started
= TRUE
;
243 result
= KERN_FAILURE
;
246 result
= KERN_TERMINATED
;
248 thread_mtx_unlock(thread
);
254 * thread_depress_abort:
256 * Prematurely abort priority depression if there is one.
259 thread_depress_abort(
260 register thread_t thread
)
262 kern_return_t result
;
264 if (thread
== THREAD_NULL
)
265 return (KERN_INVALID_ARGUMENT
);
267 thread_mtx_lock(thread
);
270 result
= thread_depress_abort_internal(thread
);
272 result
= KERN_TERMINATED
;
274 thread_mtx_unlock(thread
);
281 * Indicate that the activation should run its
282 * special handler to detect a condition.
284 * Called with thread mutex held.
290 spl_t s
= splsched();
294 if (!(thread
->state
& TH_ABORT
)) {
295 thread
->state
|= TH_ABORT
;
296 install_special_handler_locked(thread
);
299 thread
->state
&= ~TH_ABORT_SAFELY
;
301 thread_unlock(thread
);
307 register thread_t thread
)
309 kern_return_t result
= KERN_SUCCESS
;
311 if (thread
== THREAD_NULL
)
312 return (KERN_INVALID_ARGUMENT
);
314 thread_mtx_lock(thread
);
316 if (thread
->active
) {
318 clear_wait(thread
, THREAD_INTERRUPTED
);
321 result
= KERN_TERMINATED
;
323 thread_mtx_unlock(thread
);
332 kern_return_t result
= KERN_SUCCESS
;
334 if (thread
== THREAD_NULL
)
335 return (KERN_INVALID_ARGUMENT
);
337 thread_mtx_lock(thread
);
339 if (thread
->active
) {
340 spl_t s
= splsched();
343 if (!thread
->at_safe_point
||
344 clear_wait_internal(thread
, THREAD_INTERRUPTED
) != KERN_SUCCESS
) {
345 if (!(thread
->state
& TH_ABORT
)) {
346 thread
->state
|= (TH_ABORT
|TH_ABORT_SAFELY
);
347 install_special_handler_locked(thread
);
350 thread_unlock(thread
);
354 result
= KERN_TERMINATED
;
356 thread_mtx_unlock(thread
);
361 /*** backward compatibility hacks ***/
362 #include <mach/thread_info.h>
363 #include <mach/thread_special_ports.h>
364 #include <ipc/ipc_port.h>
369 thread_flavor_t flavor
,
370 thread_info_t thread_info_out
,
371 mach_msg_type_number_t
*thread_info_count
)
373 kern_return_t result
;
375 if (thread
== THREAD_NULL
)
376 return (KERN_INVALID_ARGUMENT
);
378 thread_mtx_lock(thread
);
381 result
= thread_info_internal(
382 thread
, flavor
, thread_info_out
, thread_info_count
);
384 result
= KERN_TERMINATED
;
386 thread_mtx_unlock(thread
);
393 register thread_t thread
,
395 thread_state_t state
, /* pointer to OUT array */
396 mach_msg_type_number_t
*state_count
) /*IN/OUT*/
398 kern_return_t result
= KERN_SUCCESS
;
400 if (thread
== THREAD_NULL
)
401 return (KERN_INVALID_ARGUMENT
);
403 thread_mtx_lock(thread
);
405 if (thread
->active
) {
406 if (thread
!= current_thread()) {
409 thread_mtx_unlock(thread
);
411 if (thread_stop(thread
)) {
412 thread_mtx_lock(thread
);
413 result
= machine_thread_get_state(
414 thread
, flavor
, state
, state_count
);
415 thread_unstop(thread
);
418 thread_mtx_lock(thread
);
419 result
= KERN_ABORTED
;
422 thread_release(thread
);
425 result
= machine_thread_get_state(
426 thread
, flavor
, state
, state_count
);
429 result
= KERN_TERMINATED
;
431 thread_mtx_unlock(thread
);
437 * Change thread's machine-dependent state. Called with nothing
438 * locked. Returns same way.
442 register thread_t thread
,
444 thread_state_t state
,
445 mach_msg_type_number_t state_count
)
447 kern_return_t result
= KERN_SUCCESS
;
449 if (thread
== THREAD_NULL
)
450 return (KERN_INVALID_ARGUMENT
);
452 thread_mtx_lock(thread
);
454 if (thread
->active
) {
455 if (thread
!= current_thread()) {
458 thread_mtx_unlock(thread
);
460 if (thread_stop(thread
)) {
461 thread_mtx_lock(thread
);
462 result
= machine_thread_set_state(
463 thread
, flavor
, state
, state_count
);
464 thread_unstop(thread
);
467 thread_mtx_lock(thread
);
468 result
= KERN_ABORTED
;
471 thread_release(thread
);
474 result
= machine_thread_set_state(
475 thread
, flavor
, state
, state_count
);
478 result
= KERN_TERMINATED
;
480 thread_mtx_unlock(thread
);
487 * Kernel-internal "thread" interfaces used outside this file:
490 /* Initialize (or re-initialize) a thread state. Called from execve
491 * with nothing locked, returns same way.
494 thread_state_initialize(
495 register thread_t thread
)
497 kern_return_t result
= KERN_SUCCESS
;
499 if (thread
== THREAD_NULL
)
500 return (KERN_INVALID_ARGUMENT
);
502 thread_mtx_lock(thread
);
504 if (thread
->active
) {
505 if (thread
!= current_thread()) {
508 thread_mtx_unlock(thread
);
510 if (thread_stop(thread
)) {
511 thread_mtx_lock(thread
);
512 result
= machine_thread_state_initialize( thread
);
513 thread_unstop(thread
);
516 thread_mtx_lock(thread
);
517 result
= KERN_ABORTED
;
520 thread_release(thread
);
523 result
= machine_thread_state_initialize( thread
);
526 result
= KERN_TERMINATED
;
528 thread_mtx_unlock(thread
);
536 register thread_t target
)
538 thread_t self
= current_thread();
539 kern_return_t result
= KERN_SUCCESS
;
541 if (target
== THREAD_NULL
|| target
== self
)
542 return (KERN_INVALID_ARGUMENT
);
544 thread_mtx_lock(target
);
546 if (target
->active
) {
549 thread_mtx_unlock(target
);
551 if (thread_stop(target
)) {
552 thread_mtx_lock(target
);
553 result
= machine_thread_dup(self
, target
);
554 thread_unstop(target
);
557 thread_mtx_lock(target
);
558 result
= KERN_ABORTED
;
561 thread_release(target
);
564 result
= KERN_TERMINATED
;
566 thread_mtx_unlock(target
);
575 * Set the status of the specified thread.
576 * Called with (and returns with) no locks held.
580 register thread_t thread
,
582 thread_state_t tstate
,
583 mach_msg_type_number_t count
)
586 return (thread_set_state(thread
, flavor
, tstate
, count
));
592 * Get the status of the specified thread.
596 register thread_t thread
,
598 thread_state_t tstate
,
599 mach_msg_type_number_t
*count
)
601 return (thread_get_state(thread
, flavor
, tstate
, count
));
605 * install_special_handler:
607 * Install the special returnhandler that handles suspension and
608 * termination, if it hasn't been installed already.
610 * Called with the thread mutex held.
613 install_special_handler(
616 spl_t s
= splsched();
619 install_special_handler_locked(thread
);
620 thread_unlock(thread
);
625 * install_special_handler_locked:
627 * Do the work of installing the special_handler.
629 * Called with the thread mutex and scheduling lock held.
632 install_special_handler_locked(
637 /* The work handler must always be the last ReturnHandler on the list,
638 because it can do tricky things like detach the thr_act. */
639 for (rh
= &thread
->handlers
; *rh
; rh
= &(*rh
)->next
)
642 if (rh
!= &thread
->special_handler
.next
)
643 *rh
= &thread
->special_handler
;
646 * Temporarily undepress, so target has
647 * a chance to do locking required to
648 * block itself in special_handler().
650 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
)
651 compute_priority(thread
, TRUE
);
653 thread_ast_set(thread
, AST_APC
);
655 if (thread
== current_thread())
656 ast_propagate(thread
->ast
);
658 processor_t processor
= thread
->last_processor
;
660 if ( processor
!= PROCESSOR_NULL
&&
661 processor
->state
== PROCESSOR_RUNNING
&&
662 processor
->active_thread
== thread
)
663 cause_ast_check(processor
);
668 * Activation control support routines internal to this file:
672 act_execute_returnhandlers(void)
674 thread_t thread
= current_thread();
676 thread_ast_clear(thread
, AST_APC
);
682 thread_mtx_lock(thread
);
687 rh
= thread
->handlers
;
689 thread
->handlers
= rh
->next
;
691 thread_unlock(thread
);
694 thread_mtx_unlock(thread
);
697 (*rh
->handler
)(rh
, thread
);
703 thread_unlock(thread
);
706 thread_mtx_unlock(thread
);
710 * special_handler_continue
712 * Continuation routine for the special handler blocks. It checks
713 * to see whether there has been any new suspensions. If so, it
714 * installs the special handler again. Otherwise, it checks to see
715 * if the current depression needs to be re-instated (it may have
716 * been temporarily removed in order to get to this point in a hurry).
719 special_handler_continue(void)
721 thread_t thread
= current_thread();
723 thread_mtx_lock(thread
);
725 if (thread
->suspend_count
> 0)
726 install_special_handler(thread
);
728 spl_t s
= splsched();
731 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
732 processor_t myprocessor
= thread
->last_processor
;
734 thread
->sched_pri
= DEPRESSPRI
;
735 myprocessor
->current_pri
= thread
->sched_pri
;
736 thread
->sched_mode
&= ~TH_MODE_PREEMPT
;
738 thread_unlock(thread
);
742 thread_mtx_unlock(thread
);
744 thread_exception_return();
749 * special_handler - handles suspension, termination. Called
750 * with nothing locked. Returns (if it returns) the same way.
754 __unused ReturnHandler
*rh
,
759 thread_mtx_lock(thread
);
763 thread
->state
&= ~(TH_ABORT
|TH_ABORT_SAFELY
); /* clear any aborts */
764 thread_unlock(thread
);
768 * If we're suspended, go to sleep and wait for someone to wake us up.
770 if (thread
->active
) {
771 if (thread
->suspend_count
> 0) {
772 if (thread
->handlers
== NULL
) {
773 assert_wait(&thread
->suspend_count
, THREAD_ABORTSAFE
);
774 thread_mtx_unlock(thread
);
775 thread_block((thread_continue_t
)special_handler_continue
);
779 thread_mtx_unlock(thread
);
781 special_handler_continue();
786 thread_mtx_unlock(thread
);
788 thread_terminate_self();
792 thread_mtx_unlock(thread
);
799 thread_state_t state
,
800 mach_msg_type_number_t count
)
802 if (thread
== current_thread())
803 return (KERN_INVALID_ARGUMENT
);
805 return (thread_set_state(thread
, flavor
, state
, count
));
813 thread_state_t state
,
814 mach_msg_type_number_t
*count
)
816 if (thread
== current_thread())
817 return (KERN_INVALID_ARGUMENT
);
819 return (thread_get_state(thread
, flavor
, state
, count
));
826 spl_t s
= splsched();
828 if (thread
== current_thread()) {
829 thread_ast_set(thread
, AST_BSD
);
830 ast_propagate(thread
->ast
);
833 processor_t processor
;
836 thread_ast_set(thread
, AST_BSD
);
837 processor
= thread
->last_processor
;
838 if ( processor
!= PROCESSOR_NULL
&&
839 processor
->state
== PROCESSOR_RUNNING
&&
840 processor
->active_thread
== thread
)
841 cause_ast_check(processor
);
842 thread_unlock(thread
);
852 spl_t s
= splsched();
854 if (thread
== current_thread()) {
855 thread_ast_set(thread
, AST_APC
);
856 ast_propagate(thread
->ast
);
859 processor_t processor
;
862 thread_ast_set(thread
, AST_APC
);
863 processor
= thread
->last_processor
;
864 if ( processor
!= PROCESSOR_NULL
&&
865 processor
->state
== PROCESSOR_RUNNING
&&
866 processor
->active_thread
== thread
)
867 cause_ast_check(processor
);
868 thread_unlock(thread
);