2 * Copyright (c) 2000-2004 Apple Computer, 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>
55 #include <mach_prof.h>
57 #include <mach/thread_act_server.h>
59 #include <kern/kern_types.h>
61 #include <kern/mach_param.h>
62 #include <kern/zalloc.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/profile.h>
72 #include <kern/machine.h>
74 #include <kern/syscall_subr.h>
75 #include <kern/sync_lock.h>
76 #include <kern/processor.h>
77 #include <kern/timer.h>
78 #include <mach_prof.h>
81 void act_abort(thread_t
);
82 void act_set_apc(thread_t
);
83 void install_special_handler_locked(thread_t
);
84 void special_handler_continue(void);
87 * Internal routine to terminate a thread.
88 * Sometimes called with task already locked.
91 thread_terminate_internal(
94 kern_return_t result
= KERN_SUCCESS
;
96 thread_mtx_lock(thread
);
99 thread
->active
= FALSE
;
104 clear_wait(thread
, THREAD_INTERRUPTED
);
106 clear_wait(thread
, THREAD_AWAKENED
);
107 thread
->started
= TRUE
;
111 result
= KERN_TERMINATED
;
113 thread_mtx_unlock(thread
);
115 if (thread
!= current_thread() && result
== KERN_SUCCESS
)
122 * Terminate a thread.
128 kern_return_t result
;
130 if (thread
== THREAD_NULL
)
131 return (KERN_INVALID_ARGUMENT
);
133 if ( thread
->task
== kernel_task
&&
134 thread
!= current_thread() )
135 return (KERN_FAILURE
);
137 result
= thread_terminate_internal(thread
);
140 * If a kernel thread is terminating itself, force an AST here.
141 * Kernel threads don't normally pass through the AST checking
142 * code - and all threads finish their own termination in the
143 * special handler APC.
145 if (thread
->task
== kernel_task
) {
146 ml_set_interrupts_enabled(FALSE
);
147 ast_taken(AST_APC
, TRUE
);
148 panic("thread_terminate");
155 * Suspend execution of the specified thread.
156 * This is a recursive-style suspension of the thread, a count of
157 * suspends is maintained.
159 * Called with thread mutex held.
163 register thread_t thread
)
165 if (thread
->suspend_count
++ == 0) {
166 install_special_handler(thread
);
168 thread_wakeup_one(&thread
->suspend_count
);
173 * Decrement internal suspension count, setting thread
174 * runnable when count falls to zero.
176 * Called with thread mutex held.
180 register thread_t thread
)
182 if ( thread
->suspend_count
> 0 &&
183 --thread
->suspend_count
== 0 ) {
185 thread_wakeup_one(&thread
->suspend_count
);
187 clear_wait(thread
, THREAD_AWAKENED
);
188 thread
->started
= TRUE
;
195 register thread_t thread
)
197 thread_t self
= current_thread();
198 kern_return_t result
= KERN_SUCCESS
;
200 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
201 return (KERN_INVALID_ARGUMENT
);
203 thread_mtx_lock(thread
);
205 if (thread
->active
) {
206 if ( thread
->user_stop_count
++ == 0 &&
207 thread
->suspend_count
++ == 0 ) {
208 install_special_handler(thread
);
210 thread_wakeup_one(&thread
->suspend_count
);
214 result
= KERN_TERMINATED
;
216 thread_mtx_unlock(thread
);
218 if (thread
!= self
&& result
== KERN_SUCCESS
)
226 register thread_t thread
)
228 kern_return_t result
= KERN_SUCCESS
;
230 if (thread
== THREAD_NULL
|| thread
->task
== kernel_task
)
231 return (KERN_INVALID_ARGUMENT
);
233 thread_mtx_lock(thread
);
235 if (thread
->active
) {
236 if (thread
->user_stop_count
> 0) {
237 if ( --thread
->user_stop_count
== 0 &&
238 --thread
->suspend_count
== 0 ) {
240 thread_wakeup_one(&thread
->suspend_count
);
242 clear_wait(thread
, THREAD_AWAKENED
);
243 thread
->started
= TRUE
;
248 result
= KERN_FAILURE
;
251 result
= KERN_TERMINATED
;
253 thread_mtx_unlock(thread
);
259 * thread_depress_abort:
261 * Prematurely abort priority depression if there is one.
264 thread_depress_abort(
265 register thread_t thread
)
267 kern_return_t result
;
269 if (thread
== THREAD_NULL
)
270 return (KERN_INVALID_ARGUMENT
);
272 thread_mtx_lock(thread
);
275 result
= thread_depress_abort_internal(thread
);
277 result
= KERN_TERMINATED
;
279 thread_mtx_unlock(thread
);
286 * Indicate that the activation should run its
287 * special handler to detect a condition.
289 * Called with thread mutex held.
295 spl_t s
= splsched();
299 if (!(thread
->state
& TH_ABORT
)) {
300 thread
->state
|= TH_ABORT
;
301 install_special_handler_locked(thread
);
304 thread
->state
&= ~TH_ABORT_SAFELY
;
306 thread_unlock(thread
);
312 register thread_t thread
)
314 kern_return_t result
= KERN_SUCCESS
;
316 if (thread
== THREAD_NULL
)
317 return (KERN_INVALID_ARGUMENT
);
319 thread_mtx_lock(thread
);
321 if (thread
->active
) {
323 clear_wait(thread
, THREAD_INTERRUPTED
);
326 result
= KERN_TERMINATED
;
328 thread_mtx_unlock(thread
);
337 kern_return_t result
= KERN_SUCCESS
;
339 if (thread
== THREAD_NULL
)
340 return (KERN_INVALID_ARGUMENT
);
342 thread_mtx_lock(thread
);
344 if (thread
->active
) {
345 spl_t s
= splsched();
348 if (!thread
->at_safe_point
||
349 clear_wait_internal(thread
, THREAD_INTERRUPTED
) != KERN_SUCCESS
) {
350 if (!(thread
->state
& TH_ABORT
)) {
351 thread
->state
|= (TH_ABORT
|TH_ABORT_SAFELY
);
352 install_special_handler_locked(thread
);
355 thread_unlock(thread
);
359 result
= KERN_TERMINATED
;
361 thread_mtx_unlock(thread
);
366 /*** backward compatibility hacks ***/
367 #include <mach/thread_info.h>
368 #include <mach/thread_special_ports.h>
369 #include <ipc/ipc_port.h>
374 thread_flavor_t flavor
,
375 thread_info_t thread_info_out
,
376 mach_msg_type_number_t
*thread_info_count
)
378 kern_return_t result
;
380 if (thread
== THREAD_NULL
)
381 return (KERN_INVALID_ARGUMENT
);
383 thread_mtx_lock(thread
);
386 result
= thread_info_internal(
387 thread
, flavor
, thread_info_out
, thread_info_count
);
389 result
= KERN_TERMINATED
;
391 thread_mtx_unlock(thread
);
398 register thread_t thread
,
400 thread_state_t state
, /* pointer to OUT array */
401 mach_msg_type_number_t
*state_count
) /*IN/OUT*/
403 kern_return_t result
= KERN_SUCCESS
;
405 if (thread
== THREAD_NULL
)
406 return (KERN_INVALID_ARGUMENT
);
408 thread_mtx_lock(thread
);
410 if (thread
->active
) {
411 if (thread
!= current_thread()) {
414 thread_mtx_unlock(thread
);
416 if (thread_stop(thread
)) {
417 thread_mtx_lock(thread
);
418 result
= machine_thread_get_state(
419 thread
, flavor
, state
, state_count
);
420 thread_unstop(thread
);
423 thread_mtx_lock(thread
);
424 result
= KERN_ABORTED
;
427 thread_release(thread
);
430 result
= machine_thread_get_state(
431 thread
, flavor
, state
, state_count
);
434 result
= KERN_TERMINATED
;
436 thread_mtx_unlock(thread
);
442 * Change thread's machine-dependent state. Called with nothing
443 * locked. Returns same way.
447 register thread_t thread
,
449 thread_state_t state
,
450 mach_msg_type_number_t state_count
)
452 kern_return_t result
= KERN_SUCCESS
;
454 if (thread
== THREAD_NULL
)
455 return (KERN_INVALID_ARGUMENT
);
457 thread_mtx_lock(thread
);
459 if (thread
->active
) {
460 if (thread
!= current_thread()) {
463 thread_mtx_unlock(thread
);
465 if (thread_stop(thread
)) {
466 thread_mtx_lock(thread
);
467 result
= machine_thread_set_state(
468 thread
, flavor
, state
, state_count
);
469 thread_unstop(thread
);
472 thread_mtx_lock(thread
);
473 result
= KERN_ABORTED
;
476 thread_release(thread
);
479 result
= machine_thread_set_state(
480 thread
, flavor
, state
, state_count
);
483 result
= KERN_TERMINATED
;
485 thread_mtx_unlock(thread
);
492 * Kernel-internal "thread" interfaces used outside this file:
495 /* Initialize (or re-initialize) a thread state. Called from execve
496 * with nothing locked, returns same way.
499 thread_state_initialize(
500 register thread_t thread
)
502 kern_return_t result
= KERN_SUCCESS
;
504 if (thread
== THREAD_NULL
)
505 return (KERN_INVALID_ARGUMENT
);
507 thread_mtx_lock(thread
);
509 if (thread
->active
) {
510 if (thread
!= current_thread()) {
513 thread_mtx_unlock(thread
);
515 if (thread_stop(thread
)) {
516 thread_mtx_lock(thread
);
517 result
= machine_thread_state_initialize( thread
);
518 thread_unstop(thread
);
521 thread_mtx_lock(thread
);
522 result
= KERN_ABORTED
;
525 thread_release(thread
);
528 result
= machine_thread_state_initialize( thread
);
531 result
= KERN_TERMINATED
;
533 thread_mtx_unlock(thread
);
541 register thread_t target
)
543 thread_t self
= current_thread();
544 kern_return_t result
= KERN_SUCCESS
;
546 if (target
== THREAD_NULL
|| target
== self
)
547 return (KERN_INVALID_ARGUMENT
);
549 thread_mtx_lock(target
);
551 if (target
->active
) {
554 thread_mtx_unlock(target
);
556 if (thread_stop(target
)) {
557 thread_mtx_lock(target
);
558 result
= machine_thread_dup(self
, target
);
559 thread_unstop(target
);
562 thread_mtx_lock(target
);
563 result
= KERN_ABORTED
;
566 thread_release(target
);
569 result
= KERN_TERMINATED
;
571 thread_mtx_unlock(target
);
580 * Set the status of the specified thread.
581 * Called with (and returns with) no locks held.
585 register thread_t thread
,
587 thread_state_t tstate
,
588 mach_msg_type_number_t count
)
591 return (thread_set_state(thread
, flavor
, tstate
, count
));
597 * Get the status of the specified thread.
601 register thread_t thread
,
603 thread_state_t tstate
,
604 mach_msg_type_number_t
*count
)
606 return (thread_get_state(thread
, flavor
, tstate
, count
));
610 * install_special_handler:
612 * Install the special returnhandler that handles suspension and
613 * termination, if it hasn't been installed already.
615 * Called with the thread mutex held.
618 install_special_handler(
621 spl_t s
= splsched();
624 install_special_handler_locked(thread
);
625 thread_unlock(thread
);
630 * install_special_handler_locked:
632 * Do the work of installing the special_handler.
634 * Called with the thread mutex and scheduling lock held.
637 install_special_handler_locked(
642 /* The work handler must always be the last ReturnHandler on the list,
643 because it can do tricky things like detach the thr_act. */
644 for (rh
= &thread
->handlers
; *rh
; rh
= &(*rh
)->next
)
647 if (rh
!= &thread
->special_handler
.next
)
648 *rh
= &thread
->special_handler
;
651 * Temporarily undepress, so target has
652 * a chance to do locking required to
653 * block itself in special_handler().
655 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
)
656 compute_priority(thread
, TRUE
);
658 thread_ast_set(thread
, AST_APC
);
660 if (thread
== current_thread())
661 ast_propagate(thread
->ast
);
663 processor_t processor
= thread
->last_processor
;
665 if ( processor
!= PROCESSOR_NULL
&&
666 processor
->state
== PROCESSOR_RUNNING
&&
667 processor
->active_thread
== thread
)
668 cause_ast_check(processor
);
673 * Activation control support routines internal to this file:
677 act_execute_returnhandlers(void)
679 thread_t thread
= current_thread();
681 thread_ast_clear(thread
, AST_APC
);
687 thread_mtx_lock(thread
);
692 rh
= thread
->handlers
;
694 thread
->handlers
= rh
->next
;
696 thread_unlock(thread
);
699 thread_mtx_unlock(thread
);
702 (*rh
->handler
)(rh
, thread
);
708 thread_unlock(thread
);
711 thread_mtx_unlock(thread
);
715 * special_handler_continue
717 * Continuation routine for the special handler blocks. It checks
718 * to see whether there has been any new suspensions. If so, it
719 * installs the special handler again. Otherwise, it checks to see
720 * if the current depression needs to be re-instated (it may have
721 * been temporarily removed in order to get to this point in a hurry).
724 special_handler_continue(void)
726 thread_t thread
= current_thread();
728 thread_mtx_lock(thread
);
730 if (thread
->suspend_count
> 0)
731 install_special_handler(thread
);
733 spl_t s
= splsched();
736 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
737 processor_t myprocessor
= thread
->last_processor
;
739 thread
->sched_pri
= DEPRESSPRI
;
740 myprocessor
->current_pri
= thread
->sched_pri
;
741 thread
->sched_mode
&= ~TH_MODE_PREEMPT
;
743 thread_unlock(thread
);
747 thread_mtx_unlock(thread
);
749 thread_exception_return();
754 * special_handler - handles suspension, termination. Called
755 * with nothing locked. Returns (if it returns) the same way.
759 __unused ReturnHandler
*rh
,
764 thread_mtx_lock(thread
);
768 thread
->state
&= ~(TH_ABORT
|TH_ABORT_SAFELY
); /* clear any aborts */
769 thread_unlock(thread
);
773 * If we're suspended, go to sleep and wait for someone to wake us up.
775 if (thread
->active
) {
776 if (thread
->suspend_count
> 0) {
777 if (thread
->handlers
== NULL
) {
778 assert_wait(&thread
->suspend_count
, THREAD_ABORTSAFE
);
779 thread_mtx_unlock(thread
);
780 thread_block((thread_continue_t
)special_handler_continue
);
784 thread_mtx_unlock(thread
);
786 special_handler_continue();
791 thread_mtx_unlock(thread
);
793 thread_terminate_self();
797 thread_mtx_unlock(thread
);
804 thread_state_t state
,
805 mach_msg_type_number_t count
)
807 if (thread
== current_thread())
808 return (KERN_INVALID_ARGUMENT
);
810 return (thread_set_state(thread
, flavor
, state
, count
));
818 thread_state_t state
,
819 mach_msg_type_number_t
*count
)
821 if (thread
== current_thread())
822 return (KERN_INVALID_ARGUMENT
);
824 return (thread_get_state(thread
, flavor
, state
, count
));
831 spl_t s
= splsched();
833 if (thread
== current_thread()) {
834 thread_ast_set(thread
, AST_BSD
);
835 ast_propagate(thread
->ast
);
838 processor_t processor
;
841 thread_ast_set(thread
, AST_BSD
);
842 processor
= thread
->last_processor
;
843 if ( processor
!= PROCESSOR_NULL
&&
844 processor
->state
== PROCESSOR_RUNNING
&&
845 processor
->active_thread
== thread
)
846 cause_ast_check(processor
);
847 thread_unlock(thread
);
857 spl_t s
= splsched();
859 if (thread
== current_thread()) {
860 thread_ast_set(thread
, AST_APC
);
861 ast_propagate(thread
->ast
);
864 processor_t processor
;
867 thread_ast_set(thread
, AST_APC
);
868 processor
= thread
->last_processor
;
869 if ( processor
!= PROCESSOR_NULL
&&
870 processor
->state
== PROCESSOR_RUNNING
&&
871 processor
->active_thread
== thread
)
872 cause_ast_check(processor
);
873 thread_unlock(thread
);