2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * @OSF_FREE_COPYRIGHT@
29 * Copyright (c) 1993 The University of Utah and
30 * the Center for Software Science (CSS). All rights reserved.
32 * Permission to use, copy, modify and distribute this software and its
33 * documentation is hereby granted, provided that both the copyright
34 * notice and this permission notice appear in all copies of the
35 * software, derivative works or modified versions, and any portions
36 * thereof, and that both notices appear in supporting documentation.
38 * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
39 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
40 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
42 * CSS requests users of this software to return to css-dist@cs.utah.edu any
43 * improvements that they make and grant CSS redistribution rights.
45 * Author: Bryan Ford, University of Utah CSS
47 * Thread_Activation management routines
51 #include <task_swapper.h>
52 #include <mach/kern_return.h>
53 #include <mach/alert.h>
54 #include <kern/etap_macros.h>
55 #include <kern/mach_param.h>
56 #include <kern/zalloc.h>
57 #include <kern/thread.h>
58 #include <kern/thread_swap.h>
59 #include <kern/task.h>
60 #include <kern/task_swap.h>
61 #include <kern/thread_act.h>
62 #include <kern/sched_prim.h>
63 #include <kern/misc_protos.h>
64 #include <kern/assert.h>
65 #include <kern/exception.h>
66 #include <kern/ipc_mig.h>
67 #include <kern/ipc_tt.h>
68 #include <kern/profile.h>
69 #include <kern/machine.h>
71 #include <kern/syscall_subr.h>
72 #include <kern/sync_lock.h>
73 #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/
74 #include <kern/processor.h>
75 #include <mach_prof.h>
79 * Track the number of times we need to swapin a thread to deallocate it.
81 int act_free_swapin
= 0;
84 * Forward declarations for functions local to this file.
86 kern_return_t
act_abort( thread_act_t
, boolean_t
);
87 void special_handler(ReturnHandler
*, thread_act_t
);
88 kern_return_t
act_set_state_locked(thread_act_t
, int,
90 mach_msg_type_number_t
);
91 kern_return_t
act_get_state_locked(thread_act_t
, int,
93 mach_msg_type_number_t
*);
94 void act_set_astbsd(thread_act_t
);
95 void act_set_apc(thread_act_t
);
96 void act_ulock_release_all(thread_act_t thr_act
);
98 void install_special_handler_locked(thread_act_t
);
100 static void act_disable(thread_act_t
);
103 * Thread interfaces accessed via a thread_activation:
108 * Internal routine to terminate a thread.
109 * Sometimes called with task already locked.
112 thread_terminate_internal(
113 register thread_act_t act
)
115 kern_return_t result
;
118 thread
= act_lock_thread(act
);
121 act_unlock_thread(act
);
122 return (KERN_TERMINATED
);
126 result
= act_abort(act
, FALSE
);
129 * Make sure this thread enters the kernel
130 * Must unlock the act, but leave the shuttle
131 * captured in this act.
133 if (thread
!= current_thread()) {
136 if (thread_stop(thread
))
137 thread_unstop(thread
);
139 result
= KERN_ABORTED
;
144 clear_wait(thread
, act
->started
? THREAD_INTERRUPTED
: THREAD_AWAKENED
);
145 act_unlock_thread(act
);
151 * Terminate a thread.
155 register thread_act_t act
)
157 kern_return_t result
;
159 if (act
== THR_ACT_NULL
)
160 return (KERN_INVALID_ARGUMENT
);
162 if ( act
->task
== kernel_task
&&
163 act
!= current_act() )
164 return (KERN_FAILURE
);
166 result
= thread_terminate_internal(act
);
169 * If a kernel thread is terminating itself, force an AST here.
170 * Kernel threads don't normally pass through the AST checking
171 * code - and all threads finish their own termination in the
172 * special handler APC.
174 if (act
->task
== kernel_task
) {
175 ml_set_interrupts_enabled(FALSE
);
176 assert(act
== current_act());
177 ast_taken(AST_APC
, TRUE
);
178 panic("thread_terminate");
185 * Suspend execution of the specified thread.
186 * This is a recursive-style suspension of the thread, a count of
187 * suspends is maintained.
189 * Called with act_lock held.
193 register thread_act_t act
)
195 thread_t thread
= act
->thread
;
197 if (act
->suspend_count
++ == 0) {
198 install_special_handler(act
);
200 thread
!= THREAD_NULL
&&
201 thread
->top_act
== act
)
202 thread_wakeup_one(&act
->suspend_count
);
207 * Decrement internal suspension count for thr_act, setting thread
208 * runnable when count falls to zero.
210 * Called with act_lock held.
214 register thread_act_t act
)
216 thread_t thread
= act
->thread
;
218 if ( act
->suspend_count
> 0 &&
219 --act
->suspend_count
== 0 &&
220 thread
!= THREAD_NULL
&&
221 thread
->top_act
== act
) {
223 clear_wait(thread
, THREAD_AWAKENED
);
227 thread_wakeup_one(&act
->suspend_count
);
233 register thread_act_t act
)
237 if (act
== THR_ACT_NULL
|| act
->task
== kernel_task
)
238 return (KERN_INVALID_ARGUMENT
);
240 thread
= act_lock_thread(act
);
243 act_unlock_thread(act
);
244 return (KERN_TERMINATED
);
247 if ( act
->user_stop_count
++ == 0 &&
248 act
->suspend_count
++ == 0 ) {
249 install_special_handler(act
);
250 if ( thread
!= current_thread() &&
251 thread
!= THREAD_NULL
&&
252 thread
->top_act
== act
) {
253 assert(act
->started
);
254 thread_wakeup_one(&act
->suspend_count
);
255 act_unlock_thread(act
);
260 act_unlock_thread(act
);
263 act_unlock_thread(act
);
265 return (KERN_SUCCESS
);
270 register thread_act_t act
)
272 kern_return_t result
= KERN_SUCCESS
;
275 if (act
== THR_ACT_NULL
|| act
->task
== kernel_task
)
276 return (KERN_INVALID_ARGUMENT
);
278 thread
= act_lock_thread(act
);
281 if (act
->user_stop_count
> 0) {
282 if ( --act
->user_stop_count
== 0 &&
283 --act
->suspend_count
== 0 &&
284 thread
!= THREAD_NULL
&&
285 thread
->top_act
== act
) {
287 clear_wait(thread
, THREAD_AWAKENED
);
291 thread_wakeup_one(&act
->suspend_count
);
295 result
= KERN_FAILURE
;
298 result
= KERN_TERMINATED
;
300 act_unlock_thread(act
);
306 * thread_depress_abort:
308 * Prematurely abort priority depression if there is one.
311 thread_depress_abort(
312 register thread_act_t thr_act
)
314 register thread_t thread
;
315 kern_return_t result
;
317 if (thr_act
== THR_ACT_NULL
)
318 return (KERN_INVALID_ARGUMENT
);
320 thread
= act_lock_thread(thr_act
);
321 /* if activation is terminating, this operation is not meaningful */
322 if (!thr_act
->active
) {
323 act_unlock_thread(thr_act
);
325 return (KERN_TERMINATED
);
328 result
= _mk_sp_thread_depress_abort(thread
, FALSE
);
330 act_unlock_thread(thr_act
);
337 * Indicate that the activation should run its
338 * special handler to detect the condition.
340 * Called with act_lock held.
345 boolean_t chain_break
)
347 thread_t thread
= act
->thread
;
348 spl_t s
= splsched();
350 assert(thread
->top_act
== act
);
353 if (!(thread
->state
& TH_ABORT
)) {
354 thread
->state
|= TH_ABORT
;
355 install_special_handler_locked(act
);
357 thread
->state
&= ~TH_ABORT_SAFELY
;
359 thread_unlock(thread
);
362 return (KERN_SUCCESS
);
367 register thread_act_t act
)
369 kern_return_t result
;
372 if (act
== THR_ACT_NULL
)
373 return (KERN_INVALID_ARGUMENT
);
375 thread
= act_lock_thread(act
);
378 act_unlock_thread(act
);
379 return (KERN_TERMINATED
);
382 result
= act_abort(act
, FALSE
);
383 clear_wait(thread
, THREAD_INTERRUPTED
);
384 act_unlock_thread(act
);
397 if ( act
== THR_ACT_NULL
)
398 return (KERN_INVALID_ARGUMENT
);
400 thread
= act_lock_thread(act
);
403 act_unlock_thread(act
);
404 return (KERN_TERMINATED
);
409 if (!thread
->at_safe_point
||
410 clear_wait_internal(thread
, THREAD_INTERRUPTED
) != KERN_SUCCESS
) {
411 if (!(thread
->state
& TH_ABORT
)) {
412 thread
->state
|= (TH_ABORT
|TH_ABORT_SAFELY
);
413 install_special_handler_locked(act
);
416 thread_unlock(thread
);
419 act_unlock_thread(act
);
421 return (KERN_SUCCESS
);
424 /*** backward compatibility hacks ***/
425 #include <mach/thread_info.h>
426 #include <mach/thread_special_ports.h>
427 #include <ipc/ipc_port.h>
428 #include <mach/thread_act_server.h>
432 thread_act_t thr_act
,
433 thread_flavor_t flavor
,
434 thread_info_t thread_info_out
,
435 mach_msg_type_number_t
*thread_info_count
)
437 register thread_t thread
;
438 kern_return_t result
;
440 if (thr_act
== THR_ACT_NULL
)
441 return (KERN_INVALID_ARGUMENT
);
443 thread
= act_lock_thread(thr_act
);
444 if (!thr_act
->active
) {
445 act_unlock_thread(thr_act
);
447 return (KERN_TERMINATED
);
450 result
= thread_info_shuttle(thr_act
, flavor
,
451 thread_info_out
, thread_info_count
);
453 act_unlock_thread(thr_act
);
459 * Routine: thread_get_special_port [kernel call]
461 * Clones a send right for one of the thread's
466 * KERN_SUCCESS Extracted a send right.
467 * KERN_INVALID_ARGUMENT The thread is null.
468 * KERN_FAILURE The thread is dead.
469 * KERN_INVALID_ARGUMENT Invalid special port.
473 thread_get_special_port(
474 thread_act_t thr_act
,
483 return KERN_INVALID_ARGUMENT
;
484 thread
= act_lock_thread(thr_act
);
486 case THREAD_KERNEL_PORT
:
487 whichp
= &thr_act
->ith_sself
;
491 act_unlock_thread(thr_act
);
492 return KERN_INVALID_ARGUMENT
;
495 if (!thr_act
->active
) {
496 act_unlock_thread(thr_act
);
500 port
= ipc_port_copy_send(*whichp
);
501 act_unlock_thread(thr_act
);
508 * Routine: thread_set_special_port [kernel call]
510 * Changes one of the thread's special ports,
511 * setting it to the supplied send right.
513 * Nothing locked. If successful, consumes
514 * the supplied send right.
516 * KERN_SUCCESS Changed the special port.
517 * KERN_INVALID_ARGUMENT The thread is null.
518 * KERN_FAILURE The thread is dead.
519 * KERN_INVALID_ARGUMENT Invalid special port.
523 thread_set_special_port(
524 thread_act_t thr_act
,
533 return KERN_INVALID_ARGUMENT
;
535 thread
= act_lock_thread(thr_act
);
537 case THREAD_KERNEL_PORT
:
538 whichp
= &thr_act
->ith_self
;
542 act_unlock_thread(thr_act
);
543 return KERN_INVALID_ARGUMENT
;
546 if (!thr_act
->active
) {
547 act_unlock_thread(thr_act
);
553 act_unlock_thread(thr_act
);
556 ipc_port_release_send(old
);
561 * thread state should always be accessible by locking the thread
562 * and copying it. The activation messes things up so for right
563 * now if it's not the top of the chain, use a special handler to
564 * get the information when the shuttle returns to the activation.
568 register thread_act_t act
,
570 thread_state_t state
, /* pointer to OUT array */
571 mach_msg_type_number_t
*state_count
) /*IN/OUT*/
573 kern_return_t result
= KERN_SUCCESS
;
576 if (act
== THR_ACT_NULL
|| act
== current_act())
577 return (KERN_INVALID_ARGUMENT
);
579 thread
= act_lock_thread(act
);
582 act_unlock_thread(act
);
583 return (KERN_TERMINATED
);
591 if ( thread
== THREAD_NULL
||
592 thread
->top_act
!= act
)
594 act_unlock_thread(act
);
596 if (!thread_stop(thread
)) {
597 result
= KERN_ABORTED
;
598 (void)act_lock_thread(act
);
599 thread
= THREAD_NULL
;
603 thread1
= act_lock_thread(act
);
604 if (thread1
== thread
)
607 thread_unstop(thread
);
611 if (result
== KERN_SUCCESS
)
612 result
= machine_thread_get_state(act
, flavor
, state
, state_count
);
614 if ( thread
!= THREAD_NULL
&&
615 thread
->top_act
== act
)
616 thread_unstop(thread
);
619 act_unlock_thread(act
);
625 * Change thread's machine-dependent state. Called with nothing
626 * locked. Returns same way.
630 register thread_act_t act
,
632 thread_state_t state
,
633 mach_msg_type_number_t state_count
)
635 kern_return_t result
= KERN_SUCCESS
;
638 if (act
== THR_ACT_NULL
|| act
== current_act())
639 return (KERN_INVALID_ARGUMENT
);
641 thread
= act_lock_thread(act
);
644 act_unlock_thread(act
);
645 return (KERN_TERMINATED
);
653 if ( thread
== THREAD_NULL
||
654 thread
->top_act
!= act
)
656 act_unlock_thread(act
);
658 if (!thread_stop(thread
)) {
659 result
= KERN_ABORTED
;
660 (void)act_lock_thread(act
);
661 thread
= THREAD_NULL
;
665 thread1
= act_lock_thread(act
);
666 if (thread1
== thread
)
669 thread_unstop(thread
);
673 if (result
== KERN_SUCCESS
)
674 result
= machine_thread_set_state(act
, flavor
, state
, state_count
);
676 if ( thread
!= THREAD_NULL
&&
677 thread
->top_act
== act
)
678 thread_unstop(thread
);
681 act_unlock_thread(act
);
687 * Kernel-internal "thread" interfaces used outside this file:
692 register thread_act_t target
)
694 kern_return_t result
= KERN_SUCCESS
;
695 thread_act_t self
= current_act();
698 if (target
== THR_ACT_NULL
|| target
== self
)
699 return (KERN_INVALID_ARGUMENT
);
701 thread
= act_lock_thread(target
);
703 if (!target
->active
) {
704 act_unlock_thread(target
);
705 return (KERN_TERMINATED
);
713 if ( thread
== THREAD_NULL
||
714 thread
->top_act
!= target
)
716 act_unlock_thread(target
);
718 if (!thread_stop(thread
)) {
719 result
= KERN_ABORTED
;
720 (void)act_lock_thread(target
);
721 thread
= THREAD_NULL
;
725 thread1
= act_lock_thread(target
);
726 if (thread1
== thread
)
729 thread_unstop(thread
);
733 if (result
== KERN_SUCCESS
)
734 result
= machine_thread_dup(self
, target
);
736 if ( thread
!= THREAD_NULL
&&
737 thread
->top_act
== target
)
738 thread_unstop(thread
);
740 thread_release(target
);
741 act_unlock_thread(target
);
750 * Set the status of the specified thread.
751 * Called with (and returns with) no locks held.
755 register thread_act_t act
,
757 thread_state_t tstate
,
758 mach_msg_type_number_t count
)
760 kern_return_t result
= KERN_SUCCESS
;
763 thread
= act_lock_thread(act
);
765 if ( act
!= current_act() &&
766 (act
->suspend_count
== 0 ||
767 thread
== THREAD_NULL
||
768 (thread
->state
& TH_RUN
) ||
769 thread
->top_act
!= act
) )
770 result
= KERN_FAILURE
;
772 if (result
== KERN_SUCCESS
)
773 result
= machine_thread_set_state(act
, flavor
, tstate
, count
);
775 act_unlock_thread(act
);
783 * Get the status of the specified thread.
787 register thread_act_t act
,
789 thread_state_t tstate
,
790 mach_msg_type_number_t
*count
)
792 kern_return_t result
= KERN_SUCCESS
;
795 thread
= act_lock_thread(act
);
797 if ( act
!= current_act() &&
798 (act
->suspend_count
== 0 ||
799 thread
== THREAD_NULL
||
800 (thread
->state
& TH_RUN
) ||
801 thread
->top_act
!= act
) )
802 result
= KERN_FAILURE
;
804 if (result
== KERN_SUCCESS
)
805 result
= machine_thread_get_state(act
, flavor
, tstate
, count
);
807 act_unlock_thread(act
);
813 * Kernel-internal thread_activation interfaces used outside this file:
824 act_reference_locked(act
);
841 if (--act
->act_ref_count
> 0) {
846 assert(!act
->active
);
848 thread
= act
->thread
;
849 assert(thread
!= NULL
);
851 thread
->top_act
= NULL
;
858 task_proc
= task
->bsd_info
;
861 time_value_t user_time
, system_time
;
863 thread_read_times(thread
, &user_time
, &system_time
);
864 time_value_add(&task
->total_user_time
, &user_time
);
865 time_value_add(&task
->total_system_time
, &system_time
);
867 queue_remove(&task
->threads
, act
, thread_act_t
, task_threads
);
868 act
->task_threads
.next
= NULL
;
869 task
->thread_count
--;
870 task
->res_thread_count
--;
875 act_prof_deallocate(act
);
876 ipc_thr_act_terminate(act
);
880 extern void uthread_free(task_t
, void *, void *);
881 void *ut
= act
->uthread
;
884 uthread_free(task
, ut
, task_proc
);
886 #endif /* MACH_BSD */
888 task_deallocate(task
);
890 thread_deallocate(thread
);
895 * act_attach - Attach an thr_act to the top of a thread ("push the stack").
897 * The thread_shuttle must be either the current one or a brand-new one.
898 * Assumes the thr_act is active but not in use.
900 * Already locked: thr_act plus "appropriate" thread-related locks
901 * (see act_lock_thread()).
911 * Chain the act onto the thread's act stack.
913 act
->act_ref_count
++;
914 act
->thread
= thread
;
915 act
->higher
= THR_ACT_NULL
;
916 lower
= act
->lower
= thread
->top_act
;
917 if (lower
!= THR_ACT_NULL
)
920 thread
->top_act
= act
;
926 * Remove the current thr_act from the top of the current thread, i.e.
927 * "pop the stack". Assumes already locked: thr_act plus "appropriate"
928 * thread-related locks (see act_lock_thread).
932 thread_act_t cur_act
)
934 thread_t cur_thread
= cur_act
->thread
;
936 /* Unlink the thr_act from the thread's thr_act stack */
937 cur_thread
->top_act
= cur_act
->lower
;
939 cur_act
->act_ref_count
--;
940 assert(cur_act
->act_ref_count
> 0);
943 cur_act
->lower
= cur_act
->higher
= THR_ACT_NULL
;
944 if (cur_thread
->top_act
)
945 cur_thread
->top_act
->higher
= THR_ACT_NULL
;
946 #endif /* MACH_ASSERT */
953 * Synchronize a thread operation with migration.
954 * Called with nothing locked.
955 * Returns with thr_act locked.
959 thread_act_t thr_act
)
963 * JMM - We have moved away from explicit RPC locks
964 * and towards a generic migration approach. The wait
965 * queue lock will be the point of synchronization for
966 * the shuttle linkage when this is rolled out. Until
967 * then, just lock the act.
970 return (thr_act
->thread
);
974 * Unsynchronize with migration (i.e., undo an act_lock_thread() call).
975 * Called with thr_act locked, plus thread locks held that are
976 * "correct" for thr_act's state. Returns with nothing locked.
979 act_unlock_thread(thread_act_t thr_act
)
985 * Synchronize with migration given a pointer to a shuttle (instead of an
986 * activation). Called with nothing locked; returns with all
987 * "appropriate" thread-related locks held (see act_lock_thread()).
993 thread_act_t thr_act
;
996 thr_act
= thread
->top_act
;
999 if (!act_lock_try(thr_act
)) {
1009 * Unsynchronize with an activation starting from a pointer to
1016 thread_act_t thr_act
;
1018 if (thr_act
= thread
->top_act
) {
1019 act_unlock(thr_act
);
1026 * If a new activation is given, switch to it. If not,
1027 * switch to the lower activation (pop). Returns the old
1028 * activation. This is for migration support.
1034 thread_act_t old
, new;
1037 disable_preemption();
1039 thread
= current_thread();
1042 * Find the old and new activation for switch.
1044 old
= thread
->top_act
;
1048 new->thread
= thread
;
1054 assert(new != THR_ACT_NULL
);
1055 assert(current_processor()->active_thread
== thread
);
1057 /* This is where all the work happens */
1058 machine_switch_act(thread
, old
, new);
1061 * Push or pop an activation on the chain.
1064 act_attach(new, thread
);
1070 enable_preemption();
1076 * install_special_handler
1077 * Install the special returnhandler that handles suspension and
1078 * termination, if it hasn't been installed already.
1080 * Already locked: RPC-related locks for thr_act, but not
1081 * scheduling lock (thread_lock()) of the associated thread.
1084 install_special_handler(
1085 thread_act_t thr_act
)
1088 thread_t thread
= thr_act
->thread
;
1091 thread_lock(thread
);
1092 install_special_handler_locked(thr_act
);
1093 thread_unlock(thread
);
1098 * install_special_handler_locked
1099 * Do the work of installing the special_handler.
1101 * Already locked: RPC-related locks for thr_act, plus the
1102 * scheduling lock (thread_lock()) of the associated thread.
1105 install_special_handler_locked(
1108 thread_t thread
= act
->thread
;
1111 /* The work handler must always be the last ReturnHandler on the list,
1112 because it can do tricky things like detach the thr_act. */
1113 for (rh
= &act
->handlers
; *rh
; rh
= &(*rh
)->next
)
1115 if (rh
!= &act
->special_handler
.next
)
1116 *rh
= &act
->special_handler
;
1118 if (act
== thread
->top_act
) {
1120 * Temporarily undepress, so target has
1121 * a chance to do locking required to
1122 * block itself in special_handler().
1124 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
)
1125 compute_priority(thread
, TRUE
);
1128 thread_ast_set(act
, AST_APC
);
1129 if (act
== current_act())
1130 ast_propagate(act
->ast
);
1132 processor_t processor
= thread
->last_processor
;
1134 if ( processor
!= PROCESSOR_NULL
&&
1135 processor
->state
== PROCESSOR_RUNNING
&&
1136 processor
->active_thread
== thread
)
1137 cause_ast_check(processor
);
1144 thread_apc_handler_t apc
)
1146 extern thread_apc_handler_t bsd_ast
;
1148 assert(apc
== bsd_ast
);
1149 return (KERN_FAILURE
);
1155 thread_apc_handler_t apc
)
1157 extern thread_apc_handler_t bsd_ast
;
1159 assert(apc
== bsd_ast
);
1160 return (KERN_FAILURE
);
1164 * Activation control support routines internal to this file:
1168 * act_execute_returnhandlers() - does just what the name says
1170 * This is called by system-dependent code when it detects that
1171 * thr_act->handlers is non-null while returning into user mode.
1174 act_execute_returnhandlers(void)
1176 thread_act_t act
= current_act();
1178 thread_ast_clear(act
, AST_APC
);
1183 thread_t thread
= act_lock_thread(act
);
1186 thread_lock(thread
);
1189 thread_unlock(thread
);
1191 act_unlock_thread(act
);
1194 act
->handlers
= rh
->next
;
1195 thread_unlock(thread
);
1197 act_unlock_thread(act
);
1200 (*rh
->handler
)(rh
, act
);
1205 * special_handler_continue
1207 * Continuation routine for the special handler blocks. It checks
1208 * to see whether there has been any new suspensions. If so, it
1209 * installs the special handler again. Otherwise, it checks to see
1210 * if the current depression needs to be re-instated (it may have
1211 * been temporarily removed in order to get to this point in a hurry).
1214 special_handler_continue(void)
1216 thread_act_t self
= current_act();
1218 if (self
->suspend_count
> 0)
1219 install_special_handler(self
);
1221 thread_t thread
= self
->thread
;
1222 spl_t s
= splsched();
1224 thread_lock(thread
);
1225 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
1226 processor_t myprocessor
= thread
->last_processor
;
1228 thread
->sched_pri
= DEPRESSPRI
;
1229 myprocessor
->current_pri
= thread
->sched_pri
;
1230 thread
->sched_mode
&= ~TH_MODE_PREEMPT
;
1232 thread_unlock(thread
);
1236 thread_exception_return();
1241 * special_handler - handles suspension, termination. Called
1242 * with nothing locked. Returns (if it returns) the same way.
1249 thread_t thread
= act_lock_thread(self
);
1252 assert(thread
!= THREAD_NULL
);
1255 thread_lock(thread
);
1256 thread
->state
&= ~(TH_ABORT
|TH_ABORT_SAFELY
); /* clear any aborts */
1257 thread_unlock(thread
);
1260 if (!self
->active
) {
1261 act_unlock_thread(self
);
1262 thread_terminate_self();
1267 * If we're suspended, go to sleep and wait for someone to wake us up.
1269 if (self
->suspend_count
> 0) {
1270 if (self
->handlers
== NULL
) {
1271 assert_wait(&self
->suspend_count
, THREAD_ABORTSAFE
);
1272 act_unlock_thread(self
);
1273 thread_block(special_handler_continue
);
1277 act_unlock_thread(self
);
1279 special_handler_continue();
1283 act_unlock_thread(self
);
1287 * Already locked: activation (shuttle frozen within)
1289 * Mark an activation inactive, and prepare it to terminate
1294 thread_act_t thr_act
)
1296 thr_act
->active
= 0;
1298 /* Drop the thr_act reference taken for being active.
1299 * (There is still at least one reference left:
1300 * the one we were passed.)
1301 * Inline the deallocate because thr_act is locked.
1303 act_deallocate_locked(thr_act
);
1306 typedef struct GetSetState
{
1307 struct ReturnHandler rh
;
1314 /* Local Forward decls */
1315 kern_return_t
get_set_state(
1316 thread_act_t thr_act
, int flavor
,
1317 thread_state_t state
, int *pcount
,
1318 void (*handler
)(ReturnHandler
*rh
, thread_act_t thr_act
));
1319 void get_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
);
1320 void set_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
);
1323 * get_set_state(thr_act ...)
1325 * General code to install g/set_state handler.
1326 * Called with thr_act's act_lock() and "appropriate"
1327 * thread-related locks held. (See act_lock_thread().)
1333 thread_state_t state
,
1341 /* Initialize a small parameter structure */
1342 gss
.rh
.handler
= handler
;
1343 gss
.flavor
= flavor
;
1345 gss
.pcount
= pcount
;
1346 gss
.result
= KERN_ABORTED
; /* iff wait below is interrupted */
1348 /* Add it to the thr_act's return handler list */
1349 gss
.rh
.next
= act
->handlers
;
1350 act
->handlers
= &gss
.rh
;
1354 assert(act
->thread
);
1355 assert(act
!= current_act());
1358 wait_result_t result
;
1360 if ( act
->started
&&
1361 act
->thread
->top_act
== act
)
1362 thread_wakeup_one(&act
->suspend_count
);
1365 * Wait must be interruptible to avoid deadlock (e.g.) with
1366 * task_suspend() when caller and target of get_set_state()
1369 result
= assert_wait(&gss
, THREAD_ABORTSAFE
);
1370 act_unlock_thread(act
);
1372 if (result
== THREAD_WAITING
)
1373 result
= thread_block(THREAD_CONTINUE_NULL
);
1375 assert(result
!= THREAD_WAITING
);
1377 if (gss
.result
!= KERN_ABORTED
) {
1378 assert(result
!= THREAD_INTERRUPTED
);
1382 /* JMM - What about other aborts (like BSD signals)? */
1383 if (current_act()->handlers
)
1384 act_execute_returnhandlers();
1386 act_lock_thread(act
);
1389 return (gss
.result
);
1393 set_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
)
1395 GetSetState
*gss
= (GetSetState
*)rh
;
1397 gss
->result
= machine_thread_set_state(thr_act
, gss
->flavor
,
1398 gss
->state
, *gss
->pcount
);
1399 thread_wakeup((event_t
)gss
);
1403 get_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
)
1405 GetSetState
*gss
= (GetSetState
*)rh
;
1407 gss
->result
= machine_thread_get_state(thr_act
, gss
->flavor
,
1409 (mach_msg_type_number_t
*) gss
->pcount
);
1410 thread_wakeup((event_t
)gss
);
1414 act_get_state_locked(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1415 mach_msg_type_number_t
*pcount
)
1417 return(get_set_state(thr_act
, flavor
, state
, (int*)pcount
, get_state_handler
));
1421 act_set_state_locked(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1422 mach_msg_type_number_t count
)
1424 return(get_set_state(thr_act
, flavor
, state
, (int*)&count
, set_state_handler
));
1428 act_set_state(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1429 mach_msg_type_number_t count
)
1431 if (thr_act
== THR_ACT_NULL
|| thr_act
== current_act())
1432 return(KERN_INVALID_ARGUMENT
);
1434 act_lock_thread(thr_act
);
1435 return(act_set_state_locked(thr_act
, flavor
, state
, count
));
1440 act_get_state(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1441 mach_msg_type_number_t
*pcount
)
1443 if (thr_act
== THR_ACT_NULL
|| thr_act
== current_act())
1444 return(KERN_INVALID_ARGUMENT
);
1446 act_lock_thread(thr_act
);
1447 return(act_get_state_locked(thr_act
, flavor
, state
, pcount
));
1454 spl_t s
= splsched();
1456 if (act
== current_act()) {
1457 thread_ast_set(act
, AST_BSD
);
1458 ast_propagate(act
->ast
);
1461 thread_t thread
= act
->thread
;
1462 processor_t processor
;
1464 thread_lock(thread
);
1465 thread_ast_set(act
, AST_BSD
);
1466 processor
= thread
->last_processor
;
1467 if ( processor
!= PROCESSOR_NULL
&&
1468 processor
->state
== PROCESSOR_RUNNING
&&
1469 processor
->active_thread
== thread
)
1470 cause_ast_check(processor
);
1471 thread_unlock(thread
);
1481 spl_t s
= splsched();
1483 if (act
== current_act()) {
1484 thread_ast_set(act
, AST_APC
);
1485 ast_propagate(act
->ast
);
1488 thread_t thread
= act
->thread
;
1489 processor_t processor
;
1491 thread_lock(thread
);
1492 thread_ast_set(act
, AST_APC
);
1493 processor
= thread
->last_processor
;
1494 if ( processor
!= PROCESSOR_NULL
&&
1495 processor
->state
== PROCESSOR_RUNNING
&&
1496 processor
->active_thread
== thread
)
1497 cause_ast_check(processor
);
1498 thread_unlock(thread
);
1505 act_ulock_release_all(thread_act_t thr_act
)
1509 while (!queue_empty(&thr_act
->held_ulocks
)) {
1510 ulock
= (ulock_t
) queue_first(&thr_act
->held_ulocks
);
1511 (void) lock_make_unstable(ulock
, thr_act
);
1512 (void) lock_release_internal(ulock
, thr_act
);
1517 * Provide routines (for export to other components) of things that
1518 * are implemented as macros insternally.
1523 thread_act_t self
= current_act_fast();
1525 act_reference(self
);
1530 mach_thread_self(void)
1532 thread_act_t self
= current_act_fast();
1534 act_reference(self
);