2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * @OSF_FREE_COPYRIGHT@
26 * Copyright (c) 1993 The University of Utah and
27 * the Center for Software Science (CSS). All rights reserved.
29 * Permission to use, copy, modify and distribute this software and its
30 * documentation is hereby granted, provided that both the copyright
31 * notice and this permission notice appear in all copies of the
32 * software, derivative works or modified versions, and any portions
33 * thereof, and that both notices appear in supporting documentation.
35 * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
36 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
37 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 * CSS requests users of this software to return to css-dist@cs.utah.edu any
40 * improvements that they make and grant CSS redistribution rights.
42 * Author: Bryan Ford, University of Utah CSS
44 * Thread_Activation management routines
48 #include <task_swapper.h>
49 #include <mach/kern_return.h>
50 #include <mach/alert.h>
51 #include <kern/etap_macros.h>
52 #include <kern/mach_param.h>
53 #include <kern/zalloc.h>
54 #include <kern/thread.h>
55 #include <kern/thread_swap.h>
56 #include <kern/task.h>
57 #include <kern/task_swap.h>
58 #include <kern/thread_act.h>
59 #include <kern/sched_prim.h>
60 #include <kern/misc_protos.h>
61 #include <kern/assert.h>
62 #include <kern/exception.h>
63 #include <kern/ipc_mig.h>
64 #include <kern/ipc_tt.h>
65 #include <kern/profile.h>
66 #include <kern/machine.h>
68 #include <kern/syscall_subr.h>
69 #include <kern/sync_lock.h>
70 #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/
71 #include <kern/processor.h>
72 #include <mach_prof.h>
76 * Track the number of times we need to swapin a thread to deallocate it.
78 int act_free_swapin
= 0;
81 * Forward declarations for functions local to this file.
83 kern_return_t
act_abort( thread_act_t
, boolean_t
);
84 void special_handler(ReturnHandler
*, thread_act_t
);
85 kern_return_t
act_set_state_locked(thread_act_t
, int,
87 mach_msg_type_number_t
);
88 kern_return_t
act_get_state_locked(thread_act_t
, int,
90 mach_msg_type_number_t
*);
91 void act_set_astbsd(thread_act_t
);
92 void act_set_apc(thread_act_t
);
93 void act_ulock_release_all(thread_act_t thr_act
);
95 void install_special_handler_locked(thread_act_t
);
97 static void act_disable(thread_act_t
);
100 * Thread interfaces accessed via a thread_activation:
105 * Internal routine to terminate a thread.
106 * Sometimes called with task already locked.
109 thread_terminate_internal(
110 register thread_act_t act
)
112 kern_return_t result
;
115 thread
= act_lock_thread(act
);
118 act_unlock_thread(act
);
119 return (KERN_TERMINATED
);
123 result
= act_abort(act
, FALSE
);
126 * Make sure this thread enters the kernel
127 * Must unlock the act, but leave the shuttle
128 * captured in this act.
130 if (thread
!= current_thread()) {
133 if (thread_stop(thread
))
134 thread_unstop(thread
);
136 result
= KERN_ABORTED
;
141 clear_wait(thread
, act
->started
? THREAD_INTERRUPTED
: THREAD_AWAKENED
);
142 act_unlock_thread(act
);
148 * Terminate a thread.
152 register thread_act_t act
)
154 kern_return_t result
;
156 if (act
== THR_ACT_NULL
)
157 return (KERN_INVALID_ARGUMENT
);
159 if ( act
->task
== kernel_task
&&
160 act
!= current_act() )
161 return (KERN_FAILURE
);
163 result
= thread_terminate_internal(act
);
166 * If a kernel thread is terminating itself, force an AST here.
167 * Kernel threads don't normally pass through the AST checking
168 * code - and all threads finish their own termination in the
169 * special handler APC.
171 if (act
->task
== kernel_task
) {
172 ml_set_interrupts_enabled(FALSE
);
173 assert(act
== current_act());
174 ast_taken(AST_APC
, TRUE
);
175 panic("thread_terminate");
182 * Suspend execution of the specified thread.
183 * This is a recursive-style suspension of the thread, a count of
184 * suspends is maintained.
186 * Called with act_lock held.
190 register thread_act_t act
)
192 thread_t thread
= act
->thread
;
194 if (act
->suspend_count
++ == 0) {
195 install_special_handler(act
);
197 thread
!= THREAD_NULL
&&
198 thread
->top_act
== act
)
199 thread_wakeup_one(&act
->suspend_count
);
204 * Decrement internal suspension count for thr_act, setting thread
205 * runnable when count falls to zero.
207 * Called with act_lock held.
211 register thread_act_t act
)
213 thread_t thread
= act
->thread
;
215 if ( act
->suspend_count
> 0 &&
216 --act
->suspend_count
== 0 &&
217 thread
!= THREAD_NULL
&&
218 thread
->top_act
== act
) {
220 clear_wait(thread
, THREAD_AWAKENED
);
224 thread_wakeup_one(&act
->suspend_count
);
230 register thread_act_t act
)
234 if (act
== THR_ACT_NULL
|| act
->task
== kernel_task
)
235 return (KERN_INVALID_ARGUMENT
);
237 thread
= act_lock_thread(act
);
240 act_unlock_thread(act
);
241 return (KERN_TERMINATED
);
244 if ( act
->user_stop_count
++ == 0 &&
245 act
->suspend_count
++ == 0 ) {
246 install_special_handler(act
);
247 if ( thread
!= current_thread() &&
248 thread
!= THREAD_NULL
&&
249 thread
->top_act
== act
) {
250 assert(act
->started
);
251 thread_wakeup_one(&act
->suspend_count
);
252 act_unlock_thread(act
);
257 act_unlock_thread(act
);
260 act_unlock_thread(act
);
262 return (KERN_SUCCESS
);
267 register thread_act_t act
)
269 kern_return_t result
= KERN_SUCCESS
;
272 if (act
== THR_ACT_NULL
|| act
->task
== kernel_task
)
273 return (KERN_INVALID_ARGUMENT
);
275 thread
= act_lock_thread(act
);
278 if (act
->user_stop_count
> 0) {
279 if ( --act
->user_stop_count
== 0 &&
280 --act
->suspend_count
== 0 &&
281 thread
!= THREAD_NULL
&&
282 thread
->top_act
== act
) {
284 clear_wait(thread
, THREAD_AWAKENED
);
288 thread_wakeup_one(&act
->suspend_count
);
292 result
= KERN_FAILURE
;
295 result
= KERN_TERMINATED
;
297 act_unlock_thread(act
);
303 * thread_depress_abort:
305 * Prematurely abort priority depression if there is one.
308 thread_depress_abort(
309 register thread_act_t thr_act
)
311 register thread_t thread
;
312 kern_return_t result
;
314 if (thr_act
== THR_ACT_NULL
)
315 return (KERN_INVALID_ARGUMENT
);
317 thread
= act_lock_thread(thr_act
);
318 /* if activation is terminating, this operation is not meaningful */
319 if (!thr_act
->active
) {
320 act_unlock_thread(thr_act
);
322 return (KERN_TERMINATED
);
325 result
= _mk_sp_thread_depress_abort(thread
, FALSE
);
327 act_unlock_thread(thr_act
);
334 * Indicate that the activation should run its
335 * special handler to detect the condition.
337 * Called with act_lock held.
342 boolean_t chain_break
)
344 thread_t thread
= act
->thread
;
345 spl_t s
= splsched();
347 assert(thread
->top_act
== act
);
350 if (!(thread
->state
& TH_ABORT
)) {
351 thread
->state
|= TH_ABORT
;
352 install_special_handler_locked(act
);
354 thread
->state
&= ~TH_ABORT_SAFELY
;
356 thread_unlock(thread
);
359 return (KERN_SUCCESS
);
364 register thread_act_t act
)
366 kern_return_t result
;
369 if (act
== THR_ACT_NULL
)
370 return (KERN_INVALID_ARGUMENT
);
372 thread
= act_lock_thread(act
);
375 act_unlock_thread(act
);
376 return (KERN_TERMINATED
);
379 result
= act_abort(act
, FALSE
);
380 clear_wait(thread
, THREAD_INTERRUPTED
);
381 act_unlock_thread(act
);
394 if ( act
== THR_ACT_NULL
)
395 return (KERN_INVALID_ARGUMENT
);
397 thread
= act_lock_thread(act
);
400 act_unlock_thread(act
);
401 return (KERN_TERMINATED
);
406 if (!thread
->at_safe_point
||
407 clear_wait_internal(thread
, THREAD_INTERRUPTED
) != KERN_SUCCESS
) {
408 if (!(thread
->state
& TH_ABORT
)) {
409 thread
->state
|= (TH_ABORT
|TH_ABORT_SAFELY
);
410 install_special_handler_locked(act
);
413 thread_unlock(thread
);
416 act_unlock_thread(act
);
418 return (KERN_SUCCESS
);
421 /*** backward compatibility hacks ***/
422 #include <mach/thread_info.h>
423 #include <mach/thread_special_ports.h>
424 #include <ipc/ipc_port.h>
425 #include <mach/thread_act_server.h>
429 thread_act_t thr_act
,
430 thread_flavor_t flavor
,
431 thread_info_t thread_info_out
,
432 mach_msg_type_number_t
*thread_info_count
)
434 register thread_t thread
;
435 kern_return_t result
;
437 if (thr_act
== THR_ACT_NULL
)
438 return (KERN_INVALID_ARGUMENT
);
440 thread
= act_lock_thread(thr_act
);
441 if (!thr_act
->active
) {
442 act_unlock_thread(thr_act
);
444 return (KERN_TERMINATED
);
447 result
= thread_info_shuttle(thr_act
, flavor
,
448 thread_info_out
, thread_info_count
);
450 act_unlock_thread(thr_act
);
456 * Routine: thread_get_special_port [kernel call]
458 * Clones a send right for one of the thread's
463 * KERN_SUCCESS Extracted a send right.
464 * KERN_INVALID_ARGUMENT The thread is null.
465 * KERN_FAILURE The thread is dead.
466 * KERN_INVALID_ARGUMENT Invalid special port.
470 thread_get_special_port(
471 thread_act_t thr_act
,
480 return KERN_INVALID_ARGUMENT
;
481 thread
= act_lock_thread(thr_act
);
483 case THREAD_KERNEL_PORT
:
484 whichp
= &thr_act
->ith_sself
;
488 act_unlock_thread(thr_act
);
489 return KERN_INVALID_ARGUMENT
;
492 if (!thr_act
->active
) {
493 act_unlock_thread(thr_act
);
497 port
= ipc_port_copy_send(*whichp
);
498 act_unlock_thread(thr_act
);
505 * Routine: thread_set_special_port [kernel call]
507 * Changes one of the thread's special ports,
508 * setting it to the supplied send right.
510 * Nothing locked. If successful, consumes
511 * the supplied send right.
513 * KERN_SUCCESS Changed the special port.
514 * KERN_INVALID_ARGUMENT The thread is null.
515 * KERN_FAILURE The thread is dead.
516 * KERN_INVALID_ARGUMENT Invalid special port.
520 thread_set_special_port(
521 thread_act_t thr_act
,
530 return KERN_INVALID_ARGUMENT
;
532 thread
= act_lock_thread(thr_act
);
534 case THREAD_KERNEL_PORT
:
535 whichp
= &thr_act
->ith_self
;
539 act_unlock_thread(thr_act
);
540 return KERN_INVALID_ARGUMENT
;
543 if (!thr_act
->active
) {
544 act_unlock_thread(thr_act
);
550 act_unlock_thread(thr_act
);
553 ipc_port_release_send(old
);
558 * thread state should always be accessible by locking the thread
559 * and copying it. The activation messes things up so for right
560 * now if it's not the top of the chain, use a special handler to
561 * get the information when the shuttle returns to the activation.
565 register thread_act_t act
,
567 thread_state_t state
, /* pointer to OUT array */
568 mach_msg_type_number_t
*state_count
) /*IN/OUT*/
570 kern_return_t result
= KERN_SUCCESS
;
573 if (act
== THR_ACT_NULL
|| act
== current_act())
574 return (KERN_INVALID_ARGUMENT
);
576 thread
= act_lock_thread(act
);
579 act_unlock_thread(act
);
580 return (KERN_TERMINATED
);
588 if ( thread
== THREAD_NULL
||
589 thread
->top_act
!= act
)
591 act_unlock_thread(act
);
593 if (!thread_stop(thread
)) {
594 result
= KERN_ABORTED
;
595 (void)act_lock_thread(act
);
596 thread
= THREAD_NULL
;
600 thread1
= act_lock_thread(act
);
601 if (thread1
== thread
)
604 thread_unstop(thread
);
608 if (result
== KERN_SUCCESS
)
609 result
= machine_thread_get_state(act
, flavor
, state
, state_count
);
611 if ( thread
!= THREAD_NULL
&&
612 thread
->top_act
== act
)
613 thread_unstop(thread
);
616 act_unlock_thread(act
);
622 * Change thread's machine-dependent state. Called with nothing
623 * locked. Returns same way.
627 register thread_act_t act
,
629 thread_state_t state
,
630 mach_msg_type_number_t state_count
)
632 kern_return_t result
= KERN_SUCCESS
;
635 if (act
== THR_ACT_NULL
|| act
== current_act())
636 return (KERN_INVALID_ARGUMENT
);
638 thread
= act_lock_thread(act
);
641 act_unlock_thread(act
);
642 return (KERN_TERMINATED
);
650 if ( thread
== THREAD_NULL
||
651 thread
->top_act
!= act
)
653 act_unlock_thread(act
);
655 if (!thread_stop(thread
)) {
656 result
= KERN_ABORTED
;
657 (void)act_lock_thread(act
);
658 thread
= THREAD_NULL
;
662 thread1
= act_lock_thread(act
);
663 if (thread1
== thread
)
666 thread_unstop(thread
);
670 if (result
== KERN_SUCCESS
)
671 result
= machine_thread_set_state(act
, flavor
, state
, state_count
);
673 if ( thread
!= THREAD_NULL
&&
674 thread
->top_act
== act
)
675 thread_unstop(thread
);
678 act_unlock_thread(act
);
684 * Kernel-internal "thread" interfaces used outside this file:
689 register thread_act_t target
)
691 kern_return_t result
= KERN_SUCCESS
;
692 thread_act_t self
= current_act();
695 if (target
== THR_ACT_NULL
|| target
== self
)
696 return (KERN_INVALID_ARGUMENT
);
698 thread
= act_lock_thread(target
);
700 if (!target
->active
) {
701 act_unlock_thread(target
);
702 return (KERN_TERMINATED
);
710 if ( thread
== THREAD_NULL
||
711 thread
->top_act
!= target
)
713 act_unlock_thread(target
);
715 if (!thread_stop(thread
)) {
716 result
= KERN_ABORTED
;
717 (void)act_lock_thread(target
);
718 thread
= THREAD_NULL
;
722 thread1
= act_lock_thread(target
);
723 if (thread1
== thread
)
726 thread_unstop(thread
);
730 if (result
== KERN_SUCCESS
)
731 result
= machine_thread_dup(self
, target
);
733 if ( thread
!= THREAD_NULL
&&
734 thread
->top_act
== target
)
735 thread_unstop(thread
);
737 thread_release(target
);
738 act_unlock_thread(target
);
747 * Set the status of the specified thread.
748 * Called with (and returns with) no locks held.
752 register thread_act_t act
,
754 thread_state_t tstate
,
755 mach_msg_type_number_t count
)
757 kern_return_t result
= KERN_SUCCESS
;
760 thread
= act_lock_thread(act
);
762 if ( act
!= current_act() &&
763 (act
->suspend_count
== 0 ||
764 thread
== THREAD_NULL
||
765 (thread
->state
& TH_RUN
) ||
766 thread
->top_act
!= act
) )
767 result
= KERN_FAILURE
;
769 if (result
== KERN_SUCCESS
)
770 result
= machine_thread_set_state(act
, flavor
, tstate
, count
);
772 act_unlock_thread(act
);
780 * Get the status of the specified thread.
784 register thread_act_t act
,
786 thread_state_t tstate
,
787 mach_msg_type_number_t
*count
)
789 kern_return_t result
= KERN_SUCCESS
;
792 thread
= act_lock_thread(act
);
794 if ( act
!= current_act() &&
795 (act
->suspend_count
== 0 ||
796 thread
== THREAD_NULL
||
797 (thread
->state
& TH_RUN
) ||
798 thread
->top_act
!= act
) )
799 result
= KERN_FAILURE
;
801 if (result
== KERN_SUCCESS
)
802 result
= machine_thread_get_state(act
, flavor
, tstate
, count
);
804 act_unlock_thread(act
);
810 * Kernel-internal thread_activation interfaces used outside this file:
821 act_reference_locked(act
);
838 if (--act
->act_ref_count
> 0) {
843 assert(!act
->active
);
845 thread
= act
->thread
;
846 assert(thread
!= NULL
);
848 thread
->top_act
= NULL
;
855 task_proc
= task
->bsd_info
;
858 time_value_t user_time
, system_time
;
860 thread_read_times(thread
, &user_time
, &system_time
);
861 time_value_add(&task
->total_user_time
, &user_time
);
862 time_value_add(&task
->total_system_time
, &system_time
);
864 queue_remove(&task
->threads
, act
, thread_act_t
, task_threads
);
865 act
->task_threads
.next
= NULL
;
866 task
->thread_count
--;
867 task
->res_thread_count
--;
872 act_prof_deallocate(act
);
873 ipc_thr_act_terminate(act
);
877 extern void uthread_free(task_t
, void *, void *, void *);
878 void *ut
= act
->uthread
;
880 uthread_free(task
, act
, ut
, task_proc
);
883 #endif /* MACH_BSD */
885 task_deallocate(task
);
887 thread_deallocate(thread
);
892 * act_attach - Attach an thr_act to the top of a thread ("push the stack").
894 * The thread_shuttle must be either the current one or a brand-new one.
895 * Assumes the thr_act is active but not in use.
897 * Already locked: thr_act plus "appropriate" thread-related locks
898 * (see act_lock_thread()).
908 * Chain the act onto the thread's act stack.
910 act
->act_ref_count
++;
911 act
->thread
= thread
;
912 act
->higher
= THR_ACT_NULL
;
913 lower
= act
->lower
= thread
->top_act
;
914 if (lower
!= THR_ACT_NULL
)
917 thread
->top_act
= act
;
923 * Remove the current thr_act from the top of the current thread, i.e.
924 * "pop the stack". Assumes already locked: thr_act plus "appropriate"
925 * thread-related locks (see act_lock_thread).
929 thread_act_t cur_act
)
931 thread_t cur_thread
= cur_act
->thread
;
933 /* Unlink the thr_act from the thread's thr_act stack */
934 cur_thread
->top_act
= cur_act
->lower
;
936 cur_act
->act_ref_count
--;
937 assert(cur_act
->act_ref_count
> 0);
940 cur_act
->lower
= cur_act
->higher
= THR_ACT_NULL
;
941 if (cur_thread
->top_act
)
942 cur_thread
->top_act
->higher
= THR_ACT_NULL
;
943 #endif /* MACH_ASSERT */
950 * Synchronize a thread operation with migration.
951 * Called with nothing locked.
952 * Returns with thr_act locked.
956 thread_act_t thr_act
)
960 * JMM - We have moved away from explicit RPC locks
961 * and towards a generic migration approach. The wait
962 * queue lock will be the point of synchronization for
963 * the shuttle linkage when this is rolled out. Until
964 * then, just lock the act.
967 return (thr_act
->thread
);
971 * Unsynchronize with migration (i.e., undo an act_lock_thread() call).
972 * Called with thr_act locked, plus thread locks held that are
973 * "correct" for thr_act's state. Returns with nothing locked.
976 act_unlock_thread(thread_act_t thr_act
)
982 * Synchronize with migration given a pointer to a shuttle (instead of an
983 * activation). Called with nothing locked; returns with all
984 * "appropriate" thread-related locks held (see act_lock_thread()).
990 thread_act_t thr_act
;
993 thr_act
= thread
->top_act
;
996 if (!act_lock_try(thr_act
)) {
1006 * Unsynchronize with an activation starting from a pointer to
1013 thread_act_t thr_act
;
1015 if (thr_act
= thread
->top_act
) {
1016 act_unlock(thr_act
);
1023 * If a new activation is given, switch to it. If not,
1024 * switch to the lower activation (pop). Returns the old
1025 * activation. This is for migration support.
1031 thread_act_t old
, new;
1034 disable_preemption();
1036 thread
= current_thread();
1039 * Find the old and new activation for switch.
1041 old
= thread
->top_act
;
1045 new->thread
= thread
;
1051 assert(new != THR_ACT_NULL
);
1052 assert(current_processor()->active_thread
== thread
);
1054 /* This is where all the work happens */
1055 machine_switch_act(thread
, old
, new);
1058 * Push or pop an activation on the chain.
1061 act_attach(new, thread
);
1067 enable_preemption();
1073 * install_special_handler
1074 * Install the special returnhandler that handles suspension and
1075 * termination, if it hasn't been installed already.
1077 * Already locked: RPC-related locks for thr_act, but not
1078 * scheduling lock (thread_lock()) of the associated thread.
1081 install_special_handler(
1082 thread_act_t thr_act
)
1085 thread_t thread
= thr_act
->thread
;
1088 thread_lock(thread
);
1089 install_special_handler_locked(thr_act
);
1090 thread_unlock(thread
);
1095 * install_special_handler_locked
1096 * Do the work of installing the special_handler.
1098 * Already locked: RPC-related locks for thr_act, plus the
1099 * scheduling lock (thread_lock()) of the associated thread.
1102 install_special_handler_locked(
1105 thread_t thread
= act
->thread
;
1108 /* The work handler must always be the last ReturnHandler on the list,
1109 because it can do tricky things like detach the thr_act. */
1110 for (rh
= &act
->handlers
; *rh
; rh
= &(*rh
)->next
)
1112 if (rh
!= &act
->special_handler
.next
)
1113 *rh
= &act
->special_handler
;
1115 if (act
== thread
->top_act
) {
1117 * Temporarily undepress, so target has
1118 * a chance to do locking required to
1119 * block itself in special_handler().
1121 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
)
1122 compute_priority(thread
, TRUE
);
1125 thread_ast_set(act
, AST_APC
);
1126 if (act
== current_act())
1127 ast_propagate(act
->ast
);
1129 processor_t processor
= thread
->last_processor
;
1131 if ( processor
!= PROCESSOR_NULL
&&
1132 processor
->state
== PROCESSOR_RUNNING
&&
1133 processor
->active_thread
== thread
)
1134 cause_ast_check(processor
);
1141 thread_apc_handler_t apc
)
1143 extern thread_apc_handler_t bsd_ast
;
1145 assert(apc
== bsd_ast
);
1146 return (KERN_FAILURE
);
1152 thread_apc_handler_t apc
)
1154 extern thread_apc_handler_t bsd_ast
;
1156 assert(apc
== bsd_ast
);
1157 return (KERN_FAILURE
);
1161 * Activation control support routines internal to this file:
1165 * act_execute_returnhandlers() - does just what the name says
1167 * This is called by system-dependent code when it detects that
1168 * thr_act->handlers is non-null while returning into user mode.
1171 act_execute_returnhandlers(void)
1173 thread_act_t act
= current_act();
1175 thread_ast_clear(act
, AST_APC
);
1180 thread_t thread
= act_lock_thread(act
);
1183 thread_lock(thread
);
1186 thread_unlock(thread
);
1188 act_unlock_thread(act
);
1191 act
->handlers
= rh
->next
;
1192 thread_unlock(thread
);
1194 act_unlock_thread(act
);
1197 (*rh
->handler
)(rh
, act
);
1202 * special_handler_continue
1204 * Continuation routine for the special handler blocks. It checks
1205 * to see whether there has been any new suspensions. If so, it
1206 * installs the special handler again. Otherwise, it checks to see
1207 * if the current depression needs to be re-instated (it may have
1208 * been temporarily removed in order to get to this point in a hurry).
1211 special_handler_continue(void)
1213 thread_act_t self
= current_act();
1215 if (self
->suspend_count
> 0)
1216 install_special_handler(self
);
1218 thread_t thread
= self
->thread
;
1219 spl_t s
= splsched();
1221 thread_lock(thread
);
1222 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
1223 processor_t myprocessor
= thread
->last_processor
;
1225 thread
->sched_pri
= DEPRESSPRI
;
1226 myprocessor
->current_pri
= thread
->sched_pri
;
1227 thread
->sched_mode
&= ~TH_MODE_PREEMPT
;
1229 thread_unlock(thread
);
1233 thread_exception_return();
1238 * special_handler - handles suspension, termination. Called
1239 * with nothing locked. Returns (if it returns) the same way.
1246 thread_t thread
= act_lock_thread(self
);
1249 assert(thread
!= THREAD_NULL
);
1252 thread_lock(thread
);
1253 thread
->state
&= ~(TH_ABORT
|TH_ABORT_SAFELY
); /* clear any aborts */
1254 thread_unlock(thread
);
1257 if (!self
->active
) {
1258 act_unlock_thread(self
);
1259 thread_terminate_self();
1264 * If we're suspended, go to sleep and wait for someone to wake us up.
1266 if (self
->suspend_count
> 0) {
1267 if (self
->handlers
== NULL
) {
1268 assert_wait(&self
->suspend_count
, THREAD_ABORTSAFE
);
1269 act_unlock_thread(self
);
1270 thread_block(special_handler_continue
);
1274 act_unlock_thread(self
);
1276 special_handler_continue();
1280 act_unlock_thread(self
);
1284 * Already locked: activation (shuttle frozen within)
1286 * Mark an activation inactive, and prepare it to terminate
1291 thread_act_t thr_act
)
1293 thr_act
->active
= 0;
1295 /* Drop the thr_act reference taken for being active.
1296 * (There is still at least one reference left:
1297 * the one we were passed.)
1298 * Inline the deallocate because thr_act is locked.
1300 act_deallocate_locked(thr_act
);
1303 typedef struct GetSetState
{
1304 struct ReturnHandler rh
;
1311 /* Local Forward decls */
1312 kern_return_t
get_set_state(
1313 thread_act_t thr_act
, int flavor
,
1314 thread_state_t state
, int *pcount
,
1315 void (*handler
)(ReturnHandler
*rh
, thread_act_t thr_act
));
1316 void get_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
);
1317 void set_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
);
1320 * get_set_state(thr_act ...)
1322 * General code to install g/set_state handler.
1323 * Called with thr_act's act_lock() and "appropriate"
1324 * thread-related locks held. (See act_lock_thread().)
1330 thread_state_t state
,
1338 /* Initialize a small parameter structure */
1339 gss
.rh
.handler
= handler
;
1340 gss
.flavor
= flavor
;
1342 gss
.pcount
= pcount
;
1343 gss
.result
= KERN_ABORTED
; /* iff wait below is interrupted */
1345 /* Add it to the thr_act's return handler list */
1346 gss
.rh
.next
= act
->handlers
;
1347 act
->handlers
= &gss
.rh
;
1351 assert(act
->thread
);
1352 assert(act
!= current_act());
1355 wait_result_t result
;
1357 if ( act
->started
&&
1358 act
->thread
->top_act
== act
)
1359 thread_wakeup_one(&act
->suspend_count
);
1362 * Wait must be interruptible to avoid deadlock (e.g.) with
1363 * task_suspend() when caller and target of get_set_state()
1366 result
= assert_wait(&gss
, THREAD_ABORTSAFE
);
1367 act_unlock_thread(act
);
1369 if (result
== THREAD_WAITING
)
1370 result
= thread_block(THREAD_CONTINUE_NULL
);
1372 assert(result
!= THREAD_WAITING
);
1374 if (gss
.result
!= KERN_ABORTED
) {
1375 assert(result
!= THREAD_INTERRUPTED
);
1379 /* JMM - What about other aborts (like BSD signals)? */
1380 if (current_act()->handlers
)
1381 act_execute_returnhandlers();
1383 act_lock_thread(act
);
1386 return (gss
.result
);
1390 set_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
)
1392 GetSetState
*gss
= (GetSetState
*)rh
;
1394 gss
->result
= machine_thread_set_state(thr_act
, gss
->flavor
,
1395 gss
->state
, *gss
->pcount
);
1396 thread_wakeup((event_t
)gss
);
1400 get_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
)
1402 GetSetState
*gss
= (GetSetState
*)rh
;
1404 gss
->result
= machine_thread_get_state(thr_act
, gss
->flavor
,
1406 (mach_msg_type_number_t
*) gss
->pcount
);
1407 thread_wakeup((event_t
)gss
);
1411 act_get_state_locked(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1412 mach_msg_type_number_t
*pcount
)
1414 return(get_set_state(thr_act
, flavor
, state
, (int*)pcount
, get_state_handler
));
1418 act_set_state_locked(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1419 mach_msg_type_number_t count
)
1421 return(get_set_state(thr_act
, flavor
, state
, (int*)&count
, set_state_handler
));
1425 act_set_state(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1426 mach_msg_type_number_t count
)
1428 if (thr_act
== THR_ACT_NULL
|| thr_act
== current_act())
1429 return(KERN_INVALID_ARGUMENT
);
1431 act_lock_thread(thr_act
);
1432 return(act_set_state_locked(thr_act
, flavor
, state
, count
));
1437 act_get_state(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1438 mach_msg_type_number_t
*pcount
)
1440 if (thr_act
== THR_ACT_NULL
|| thr_act
== current_act())
1441 return(KERN_INVALID_ARGUMENT
);
1443 act_lock_thread(thr_act
);
1444 return(act_get_state_locked(thr_act
, flavor
, state
, pcount
));
1451 spl_t s
= splsched();
1453 if (act
== current_act()) {
1454 thread_ast_set(act
, AST_BSD
);
1455 ast_propagate(act
->ast
);
1458 thread_t thread
= act
->thread
;
1459 processor_t processor
;
1461 thread_lock(thread
);
1462 thread_ast_set(act
, AST_BSD
);
1463 processor
= thread
->last_processor
;
1464 if ( processor
!= PROCESSOR_NULL
&&
1465 processor
->state
== PROCESSOR_RUNNING
&&
1466 processor
->active_thread
== thread
)
1467 cause_ast_check(processor
);
1468 thread_unlock(thread
);
1478 spl_t s
= splsched();
1480 if (act
== current_act()) {
1481 thread_ast_set(act
, AST_APC
);
1482 ast_propagate(act
->ast
);
1485 thread_t thread
= act
->thread
;
1486 processor_t processor
;
1488 thread_lock(thread
);
1489 thread_ast_set(act
, AST_APC
);
1490 processor
= thread
->last_processor
;
1491 if ( processor
!= PROCESSOR_NULL
&&
1492 processor
->state
== PROCESSOR_RUNNING
&&
1493 processor
->active_thread
== thread
)
1494 cause_ast_check(processor
);
1495 thread_unlock(thread
);
1502 act_ulock_release_all(thread_act_t thr_act
)
1506 while (!queue_empty(&thr_act
->held_ulocks
)) {
1507 ulock
= (ulock_t
) queue_first(&thr_act
->held_ulocks
);
1508 (void) lock_make_unstable(ulock
, thr_act
);
1509 (void) lock_release_internal(ulock
, thr_act
);
1514 * Provide routines (for export to other components) of things that
1515 * are implemented as macros insternally.
1520 thread_act_t self
= current_act_fast();
1522 act_reference(self
);
1527 mach_thread_self(void)
1529 thread_act_t self
= current_act_fast();
1531 act_reference(self
);