2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * @OSF_FREE_COPYRIGHT@
34 * Copyright (c) 1993 The University of Utah and
35 * the Center for Software Science (CSS). All rights reserved.
37 * Permission to use, copy, modify and distribute this software and its
38 * documentation is hereby granted, provided that both the copyright
39 * notice and this permission notice appear in all copies of the
40 * software, derivative works or modified versions, and any portions
41 * thereof, and that both notices appear in supporting documentation.
43 * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
44 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
45 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47 * CSS requests users of this software to return to css-dist@cs.utah.edu any
48 * improvements that they make and grant CSS redistribution rights.
50 * Author: Bryan Ford, University of Utah CSS
52 * Thread management routines
54 #include <mach/mach_types.h>
55 #include <mach/kern_return.h>
56 #include <mach/alert.h>
57 #include <mach_prof.h>
59 #include <mach/thread_act_server.h>
61 #include <kern/kern_types.h>
63 #include <kern/mach_param.h>
64 #include <kern/zalloc.h>
65 #include <kern/thread.h>
66 #include <kern/task.h>
67 #include <kern/sched_prim.h>
68 #include <kern/misc_protos.h>
69 #include <kern/assert.h>
70 #include <kern/exception.h>
71 #include <kern/ipc_mig.h>
72 #include <kern/ipc_tt.h>
73 #include <kern/profile.h>
74 #include <kern/machine.h>
76 #include <kern/syscall_subr.h>
77 #include <kern/sync_lock.h>
78 #include <kern/processor.h>
79 #include <kern/timer.h>
80 #include <mach_prof.h>
83 void act_abort(thread_t
);
84 void act_set_apc(thread_t
);
85 void install_special_handler_locked(thread_t
);
86 void special_handler_continue(void);
89 * Internal routine to terminate a thread.
90 * Sometimes called with task already locked.
93 thread_terminate_internal(
96 kern_return_t result
= KERN_SUCCESS
;
98 thread_mtx_lock(thread
);
100 if (thread
->active
) {
101 thread
->active
= FALSE
;
106 clear_wait(thread
, THREAD_INTERRUPTED
);
108 clear_wait(thread
, THREAD_AWAKENED
);
109 thread
->started
= TRUE
;
113 result
= KERN_TERMINATED
;
115 thread_mtx_unlock(thread
);
117 if (thread
!= current_thread() && result
== KERN_SUCCESS
)
124 * Terminate a thread.
130 kern_return_t result
;
132 if (thread
== THREAD_NULL
)
133 return (KERN_INVALID_ARGUMENT
);
135 if ( thread
->task
== kernel_task
&&
136 thread
!= current_thread() )
137 return (KERN_FAILURE
);
139 result
= thread_terminate_internal(thread
);
142 * If a kernel thread is terminating itself, force an AST here.
143 * Kernel threads don't normally pass through the AST checking
144 * code - and all threads finish their own termination in the
145 * special handler APC.
147 if (thread
->task
== kernel_task
) {
148 ml_set_interrupts_enabled(FALSE
);
149 ast_taken(AST_APC
, TRUE
);
150 panic("thread_terminate");
157 * Suspend execution of the specified thread.
158 * This is a recursive-style suspension of the thread, a count of
159 * suspends is maintained.
161 * Called with thread mutex held.
165 register thread_t thread
)
167 if (thread
->suspend_count
++ == 0) {
168 install_special_handler(thread
);
170 thread_wakeup_one(&thread
->suspend_count
);
175 * Decrement internal suspension count, setting thread
176 * runnable when count falls to zero.
178 * Called with thread mutex held.
182 register thread_t thread
)
184 if ( thread
->suspend_count
> 0 &&
185 --thread
->suspend_count
== 0 ) {
187 thread_wakeup_one(&thread
->suspend_count
);
189 clear_wait(thread
, THREAD_AWAKENED
);
190 thread
->started
= TRUE
;
197 register thread_t thread
)
199 thread_t self
= current_thread();
200 kern_return_t result
= KERN_SUCCESS
;
202 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
203 return (KERN_INVALID_ARGUMENT
);
205 thread_mtx_lock(thread
);
207 if (thread
->active
) {
208 if ( thread
->user_stop_count
++ == 0 &&
209 thread
->suspend_count
++ == 0 ) {
210 install_special_handler(thread
);
212 thread_wakeup_one(&thread
->suspend_count
);
216 result
= KERN_TERMINATED
;
218 thread_mtx_unlock(thread
);
220 if (thread
!= self
&& result
== KERN_SUCCESS
)
228 register thread_t thread
)
230 kern_return_t result
= KERN_SUCCESS
;
232 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
233 return (KERN_INVALID_ARGUMENT
);
235 thread_mtx_lock(thread
);
237 if (thread
->active
) {
238 if (thread
->user_stop_count
> 0) {
239 if ( --thread
->user_stop_count
== 0 &&
240 --thread
->suspend_count
== 0 ) {
242 thread_wakeup_one(&thread
->suspend_count
);
244 clear_wait(thread
, THREAD_AWAKENED
);
245 thread
->started
= TRUE
;
250 result
= KERN_FAILURE
;
253 result
= KERN_TERMINATED
;
255 thread_mtx_unlock(thread
);
261 * thread_depress_abort:
263 * Prematurely abort priority depression if there is one.
266 thread_depress_abort(
267 register thread_t thread
)
269 kern_return_t result
;
271 if (thread
== THREAD_NULL
)
272 return (KERN_INVALID_ARGUMENT
);
274 thread_mtx_lock(thread
);
277 result
= thread_depress_abort_internal(thread
);
279 result
= KERN_TERMINATED
;
281 thread_mtx_unlock(thread
);
288 * Indicate that the activation should run its
289 * special handler to detect a condition.
291 * Called with thread mutex held.
297 spl_t s
= splsched();
301 if (!(thread
->state
& TH_ABORT
)) {
302 thread
->state
|= TH_ABORT
;
303 install_special_handler_locked(thread
);
306 thread
->state
&= ~TH_ABORT_SAFELY
;
308 thread_unlock(thread
);
314 register thread_t thread
)
316 kern_return_t result
= KERN_SUCCESS
;
318 if (thread
== THREAD_NULL
)
319 return (KERN_INVALID_ARGUMENT
);
321 thread_mtx_lock(thread
);
323 if (thread
->active
) {
325 clear_wait(thread
, THREAD_INTERRUPTED
);
328 result
= KERN_TERMINATED
;
330 thread_mtx_unlock(thread
);
339 kern_return_t result
= KERN_SUCCESS
;
341 if (thread
== THREAD_NULL
)
342 return (KERN_INVALID_ARGUMENT
);
344 thread_mtx_lock(thread
);
346 if (thread
->active
) {
347 spl_t s
= splsched();
350 if (!thread
->at_safe_point
||
351 clear_wait_internal(thread
, THREAD_INTERRUPTED
) != KERN_SUCCESS
) {
352 if (!(thread
->state
& TH_ABORT
)) {
353 thread
->state
|= (TH_ABORT
|TH_ABORT_SAFELY
);
354 install_special_handler_locked(thread
);
357 thread_unlock(thread
);
361 result
= KERN_TERMINATED
;
363 thread_mtx_unlock(thread
);
368 /*** backward compatibility hacks ***/
369 #include <mach/thread_info.h>
370 #include <mach/thread_special_ports.h>
371 #include <ipc/ipc_port.h>
376 thread_flavor_t flavor
,
377 thread_info_t thread_info_out
,
378 mach_msg_type_number_t
*thread_info_count
)
380 kern_return_t result
;
382 if (thread
== THREAD_NULL
)
383 return (KERN_INVALID_ARGUMENT
);
385 thread_mtx_lock(thread
);
388 result
= thread_info_internal(
389 thread
, flavor
, thread_info_out
, thread_info_count
);
391 result
= KERN_TERMINATED
;
393 thread_mtx_unlock(thread
);
400 register thread_t thread
,
402 thread_state_t state
, /* pointer to OUT array */
403 mach_msg_type_number_t
*state_count
) /*IN/OUT*/
405 kern_return_t result
= KERN_SUCCESS
;
407 if (thread
== THREAD_NULL
)
408 return (KERN_INVALID_ARGUMENT
);
410 thread_mtx_lock(thread
);
412 if (thread
->active
) {
413 if (thread
!= current_thread()) {
416 thread_mtx_unlock(thread
);
418 if (thread_stop(thread
)) {
419 thread_mtx_lock(thread
);
420 result
= machine_thread_get_state(
421 thread
, flavor
, state
, state_count
);
422 thread_unstop(thread
);
425 thread_mtx_lock(thread
);
426 result
= KERN_ABORTED
;
429 thread_release(thread
);
432 result
= machine_thread_get_state(
433 thread
, flavor
, state
, state_count
);
436 result
= KERN_TERMINATED
;
438 thread_mtx_unlock(thread
);
444 * Change thread's machine-dependent state. Called with nothing
445 * locked. Returns same way.
449 register thread_t thread
,
451 thread_state_t state
,
452 mach_msg_type_number_t state_count
)
454 kern_return_t result
= KERN_SUCCESS
;
456 if (thread
== THREAD_NULL
)
457 return (KERN_INVALID_ARGUMENT
);
459 thread_mtx_lock(thread
);
461 if (thread
->active
) {
462 if (thread
!= current_thread()) {
465 thread_mtx_unlock(thread
);
467 if (thread_stop(thread
)) {
468 thread_mtx_lock(thread
);
469 result
= machine_thread_set_state(
470 thread
, flavor
, state
, state_count
);
471 thread_unstop(thread
);
474 thread_mtx_lock(thread
);
475 result
= KERN_ABORTED
;
478 thread_release(thread
);
481 result
= machine_thread_set_state(
482 thread
, flavor
, state
, state_count
);
485 result
= KERN_TERMINATED
;
487 thread_mtx_unlock(thread
);
494 * Kernel-internal "thread" interfaces used outside this file:
497 /* Initialize (or re-initialize) a thread state. Called from execve
498 * with nothing locked, returns same way.
501 thread_state_initialize(
502 register thread_t thread
)
504 kern_return_t result
= KERN_SUCCESS
;
506 if (thread
== THREAD_NULL
)
507 return (KERN_INVALID_ARGUMENT
);
509 thread_mtx_lock(thread
);
511 if (thread
->active
) {
512 if (thread
!= current_thread()) {
515 thread_mtx_unlock(thread
);
517 if (thread_stop(thread
)) {
518 thread_mtx_lock(thread
);
519 result
= machine_thread_state_initialize( thread
);
520 thread_unstop(thread
);
523 thread_mtx_lock(thread
);
524 result
= KERN_ABORTED
;
527 thread_release(thread
);
530 result
= machine_thread_state_initialize( thread
);
533 result
= KERN_TERMINATED
;
535 thread_mtx_unlock(thread
);
543 register thread_t target
)
545 thread_t self
= current_thread();
546 kern_return_t result
= KERN_SUCCESS
;
548 if (target
== THREAD_NULL
|| target
== self
)
549 return (KERN_INVALID_ARGUMENT
);
551 thread_mtx_lock(target
);
553 if (target
->active
) {
556 thread_mtx_unlock(target
);
558 if (thread_stop(target
)) {
559 thread_mtx_lock(target
);
560 result
= machine_thread_dup(self
, target
);
561 thread_unstop(target
);
564 thread_mtx_lock(target
);
565 result
= KERN_ABORTED
;
568 thread_release(target
);
571 result
= KERN_TERMINATED
;
573 thread_mtx_unlock(target
);
582 * Set the status of the specified thread.
583 * Called with (and returns with) no locks held.
587 register thread_t thread
,
589 thread_state_t tstate
,
590 mach_msg_type_number_t count
)
593 return (thread_set_state(thread
, flavor
, tstate
, count
));
599 * Get the status of the specified thread.
603 register thread_t thread
,
605 thread_state_t tstate
,
606 mach_msg_type_number_t
*count
)
608 return (thread_get_state(thread
, flavor
, tstate
, count
));
612 * install_special_handler:
614 * Install the special returnhandler that handles suspension and
615 * termination, if it hasn't been installed already.
617 * Called with the thread mutex held.
620 install_special_handler(
623 spl_t s
= splsched();
626 install_special_handler_locked(thread
);
627 thread_unlock(thread
);
632 * install_special_handler_locked:
634 * Do the work of installing the special_handler.
636 * Called with the thread mutex and scheduling lock held.
639 install_special_handler_locked(
644 /* The work handler must always be the last ReturnHandler on the list,
645 because it can do tricky things like detach the thr_act. */
646 for (rh
= &thread
->handlers
; *rh
; rh
= &(*rh
)->next
)
649 if (rh
!= &thread
->special_handler
.next
)
650 *rh
= &thread
->special_handler
;
653 * Temporarily undepress, so target has
654 * a chance to do locking required to
655 * block itself in special_handler().
657 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
)
658 compute_priority(thread
, TRUE
);
660 thread_ast_set(thread
, AST_APC
);
662 if (thread
== current_thread())
663 ast_propagate(thread
->ast
);
665 processor_t processor
= thread
->last_processor
;
667 if ( processor
!= PROCESSOR_NULL
&&
668 processor
->state
== PROCESSOR_RUNNING
&&
669 processor
->active_thread
== thread
)
670 cause_ast_check(processor
);
675 * Activation control support routines internal to this file:
679 act_execute_returnhandlers(void)
681 thread_t thread
= current_thread();
683 thread_ast_clear(thread
, AST_APC
);
689 thread_mtx_lock(thread
);
694 rh
= thread
->handlers
;
696 thread
->handlers
= rh
->next
;
698 thread_unlock(thread
);
701 thread_mtx_unlock(thread
);
704 (*rh
->handler
)(rh
, thread
);
710 thread_unlock(thread
);
713 thread_mtx_unlock(thread
);
717 * special_handler_continue
719 * Continuation routine for the special handler blocks. It checks
720 * to see whether there has been any new suspensions. If so, it
721 * installs the special handler again. Otherwise, it checks to see
722 * if the current depression needs to be re-instated (it may have
723 * been temporarily removed in order to get to this point in a hurry).
726 special_handler_continue(void)
728 thread_t thread
= current_thread();
730 thread_mtx_lock(thread
);
732 if (thread
->suspend_count
> 0)
733 install_special_handler(thread
);
735 spl_t s
= splsched();
738 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
739 processor_t myprocessor
= thread
->last_processor
;
741 thread
->sched_pri
= DEPRESSPRI
;
742 myprocessor
->current_pri
= thread
->sched_pri
;
743 thread
->sched_mode
&= ~TH_MODE_PREEMPT
;
745 thread_unlock(thread
);
749 thread_mtx_unlock(thread
);
751 thread_exception_return();
756 * special_handler - handles suspension, termination. Called
757 * with nothing locked. Returns (if it returns) the same way.
761 __unused ReturnHandler
*rh
,
766 thread_mtx_lock(thread
);
770 thread
->state
&= ~(TH_ABORT
|TH_ABORT_SAFELY
); /* clear any aborts */
771 thread_unlock(thread
);
775 * If we're suspended, go to sleep and wait for someone to wake us up.
777 if (thread
->active
) {
778 if (thread
->suspend_count
> 0) {
779 if (thread
->handlers
== NULL
) {
780 assert_wait(&thread
->suspend_count
, THREAD_ABORTSAFE
);
781 thread_mtx_unlock(thread
);
782 thread_block((thread_continue_t
)special_handler_continue
);
786 thread_mtx_unlock(thread
);
788 special_handler_continue();
793 thread_mtx_unlock(thread
);
795 thread_terminate_self();
799 thread_mtx_unlock(thread
);
806 thread_state_t state
,
807 mach_msg_type_number_t count
)
809 if (thread
== current_thread())
810 return (KERN_INVALID_ARGUMENT
);
812 return (thread_set_state(thread
, flavor
, state
, count
));
820 thread_state_t state
,
821 mach_msg_type_number_t
*count
)
823 if (thread
== current_thread())
824 return (KERN_INVALID_ARGUMENT
);
826 return (thread_get_state(thread
, flavor
, state
, count
));
833 spl_t s
= splsched();
835 if (thread
== current_thread()) {
836 thread_ast_set(thread
, AST_BSD
);
837 ast_propagate(thread
->ast
);
840 processor_t processor
;
843 thread_ast_set(thread
, AST_BSD
);
844 processor
= thread
->last_processor
;
845 if ( processor
!= PROCESSOR_NULL
&&
846 processor
->state
== PROCESSOR_RUNNING
&&
847 processor
->active_thread
== thread
)
848 cause_ast_check(processor
);
849 thread_unlock(thread
);
859 spl_t s
= splsched();
861 if (thread
== current_thread()) {
862 thread_ast_set(thread
, AST_APC
);
863 ast_propagate(thread
->ast
);
866 processor_t processor
;
869 thread_ast_set(thread
, AST_APC
);
870 processor
= thread
->last_processor
;
871 if ( processor
!= PROCESSOR_NULL
&&
872 processor
->state
== PROCESSOR_RUNNING
&&
873 processor
->active_thread
== thread
)
874 cause_ast_check(processor
);
875 thread_unlock(thread
);