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 * Debugging printf control
82 unsigned int watchacts
= 0 /* WA_ALL */
83 ; /* Do-it-yourself & patchable */
87 * Track the number of times we need to swapin a thread to deallocate it.
89 int act_free_swapin
= 0;
93 * Forward declarations for functions local to this file.
95 kern_return_t
act_abort( thread_act_t
, boolean_t
);
96 void special_handler(ReturnHandler
*, thread_act_t
);
97 kern_return_t
act_set_state_locked(thread_act_t
, int,
99 mach_msg_type_number_t
);
100 kern_return_t
act_get_state_locked(thread_act_t
, int,
102 mach_msg_type_number_t
*);
103 void act_set_astbsd(thread_act_t
);
104 void act_set_apc(thread_act_t
);
105 void act_user_to_kernel(thread_act_t
);
106 void act_ulock_release_all(thread_act_t thr_act
);
108 void install_special_handler_locked(thread_act_t
);
110 static void act_disable(thread_act_t
);
112 struct thread_activation pageout_act
;
114 static zone_t thr_act_zone
;
117 * Thread interfaces accessed via a thread_activation:
122 * Internal routine to terminate a thread.
123 * Sometimes called with task already locked.
126 thread_terminate_internal(
127 register thread_act_t act
)
129 kern_return_t result
;
132 thread
= act_lock_thread(act
);
135 act_unlock_thread(act
);
136 return (KERN_TERMINATED
);
140 result
= act_abort(act
, FALSE
);
143 * Make sure this thread enters the kernel
144 * Must unlock the act, but leave the shuttle
145 * captured in this act.
147 if (thread
!= current_thread()) {
150 if (thread_stop(thread
))
151 thread_unstop(thread
);
153 result
= KERN_ABORTED
;
158 clear_wait(thread
, act
->inited
? THREAD_INTERRUPTED
: THREAD_AWAKENED
);
159 act_unlock_thread(act
);
165 * Terminate a thread.
169 register thread_act_t act
)
171 kern_return_t result
;
173 if (act
== THR_ACT_NULL
)
174 return (KERN_INVALID_ARGUMENT
);
176 if ( (act
->task
== kernel_task
||
177 act
->kernel_loaded
) &&
178 act
!= current_act() )
179 return (KERN_FAILURE
);
181 result
= thread_terminate_internal(act
);
184 * If a kernel thread is terminating itself, force an AST here.
185 * Kernel threads don't normally pass through the AST checking
186 * code - and all threads finish their own termination in the
187 * special handler APC.
189 if ( act
->task
== kernel_task
||
190 act
->kernel_loaded
) {
191 assert(act
== current_act());
192 ast_taken(AST_APC
, FALSE
);
193 panic("thread_terminate");
200 * Suspend execution of the specified thread.
201 * This is a recursive-style suspension of the thread, a count of
202 * suspends is maintained.
204 * Called with act_lock held.
208 register thread_act_t act
)
210 thread_t thread
= act
->thread
;
212 if (act
->suspend_count
++ == 0) {
213 install_special_handler(act
);
215 thread
!= THREAD_NULL
&&
216 thread
->top_act
== act
)
217 thread_wakeup_one(&act
->suspend_count
);
222 * Decrement internal suspension count for thr_act, setting thread
223 * runnable when count falls to zero.
225 * Called with act_lock held.
229 register thread_act_t act
)
231 thread_t thread
= act
->thread
;
233 if ( act
->suspend_count
> 0 &&
234 --act
->suspend_count
== 0 &&
235 thread
!= THREAD_NULL
&&
236 thread
->top_act
== act
) {
238 clear_wait(thread
, THREAD_AWAKENED
);
242 thread_wakeup_one(&act
->suspend_count
);
248 register thread_act_t act
)
252 if (act
== THR_ACT_NULL
)
253 return (KERN_INVALID_ARGUMENT
);
255 thread
= act_lock_thread(act
);
258 act_unlock_thread(act
);
259 return (KERN_TERMINATED
);
262 if ( act
->user_stop_count
++ == 0 &&
263 act
->suspend_count
++ == 0 ) {
264 install_special_handler(act
);
265 if ( thread
!= current_thread() &&
266 thread
!= THREAD_NULL
&&
267 thread
->top_act
== act
) {
269 thread_wakeup_one(&act
->suspend_count
);
270 act_unlock_thread(act
);
275 act_unlock_thread(act
);
278 act_unlock_thread(act
);
280 return (KERN_SUCCESS
);
285 register thread_act_t act
)
287 kern_return_t result
= KERN_SUCCESS
;
290 if (act
== THR_ACT_NULL
)
291 return (KERN_INVALID_ARGUMENT
);
293 thread
= act_lock_thread(act
);
296 if (act
->user_stop_count
> 0) {
297 if ( --act
->user_stop_count
== 0 &&
298 --act
->suspend_count
== 0 &&
299 thread
!= THREAD_NULL
&&
300 thread
->top_act
== act
) {
302 clear_wait(thread
, THREAD_AWAKENED
);
306 thread_wakeup_one(&act
->suspend_count
);
310 result
= KERN_FAILURE
;
313 result
= KERN_TERMINATED
;
315 act_unlock_thread(act
);
321 * This routine walks toward the head of an RPC chain starting at
322 * a specified thread activation. An alert bit is set and a special
323 * handler is installed for each thread it encounters.
325 * The target thread act and thread shuttle are already locked.
329 register thread_act_t act
,
336 * thread_depress_abort:
338 * Prematurely abort priority depression if there is one.
341 thread_depress_abort(
342 register thread_act_t thr_act
)
344 register thread_t thread
;
345 kern_return_t result
;
347 if (thr_act
== THR_ACT_NULL
)
348 return (KERN_INVALID_ARGUMENT
);
350 thread
= act_lock_thread(thr_act
);
351 /* if activation is terminating, this operation is not meaningful */
352 if (!thr_act
->active
) {
353 act_unlock_thread(thr_act
);
355 return (KERN_TERMINATED
);
358 result
= _mk_sp_thread_depress_abort(thread
, FALSE
);
360 act_unlock_thread(thr_act
);
367 * Indicate that the activation should run its
368 * special handler to detect the condition.
370 * Called with act_lock held.
375 boolean_t chain_break
)
377 thread_t thread
= act
->thread
;
378 spl_t s
= splsched();
380 assert(thread
->top_act
== act
);
383 if (!(thread
->state
& TH_ABORT
)) {
384 thread
->state
|= TH_ABORT
;
385 install_special_handler_locked(act
);
387 thread
->state
&= ~TH_ABORT_SAFELY
;
389 thread_unlock(thread
);
392 return (KERN_SUCCESS
);
397 register thread_act_t act
)
399 kern_return_t result
;
402 if (act
== THR_ACT_NULL
)
403 return (KERN_INVALID_ARGUMENT
);
405 thread
= act_lock_thread(act
);
408 act_unlock_thread(act
);
409 return (KERN_TERMINATED
);
412 result
= act_abort(act
, FALSE
);
413 clear_wait(thread
, THREAD_INTERRUPTED
);
414 act_unlock_thread(act
);
427 if ( act
== THR_ACT_NULL
)
428 return (KERN_INVALID_ARGUMENT
);
430 thread
= act_lock_thread(act
);
433 act_unlock_thread(act
);
434 return (KERN_TERMINATED
);
439 if (!thread
->at_safe_point
||
440 clear_wait_internal(thread
, THREAD_INTERRUPTED
) != KERN_SUCCESS
) {
441 if (!(thread
->state
& TH_ABORT
)) {
442 thread
->state
|= (TH_ABORT
|TH_ABORT_SAFELY
);
443 install_special_handler_locked(act
);
446 thread_unlock(thread
);
449 act_unlock_thread(act
);
451 return (KERN_SUCCESS
);
454 /*** backward compatibility hacks ***/
455 #include <mach/thread_info.h>
456 #include <mach/thread_special_ports.h>
457 #include <ipc/ipc_port.h>
458 #include <mach/thread_act_server.h>
462 thread_act_t thr_act
,
463 thread_flavor_t flavor
,
464 thread_info_t thread_info_out
,
465 mach_msg_type_number_t
*thread_info_count
)
467 register thread_t thread
;
468 kern_return_t result
;
470 if (thr_act
== THR_ACT_NULL
)
471 return (KERN_INVALID_ARGUMENT
);
473 thread
= act_lock_thread(thr_act
);
474 if (!thr_act
->active
) {
475 act_unlock_thread(thr_act
);
477 return (KERN_TERMINATED
);
480 result
= thread_info_shuttle(thr_act
, flavor
,
481 thread_info_out
, thread_info_count
);
483 act_unlock_thread(thr_act
);
489 * Routine: thread_get_special_port [kernel call]
491 * Clones a send right for one of the thread's
496 * KERN_SUCCESS Extracted a send right.
497 * KERN_INVALID_ARGUMENT The thread is null.
498 * KERN_FAILURE The thread is dead.
499 * KERN_INVALID_ARGUMENT Invalid special port.
503 thread_get_special_port(
504 thread_act_t thr_act
,
513 if (watchacts
& WA_PORT
)
514 printf("thread_get_special_port(thr_act=%x, which=%x port@%x=%x\n",
515 thr_act
, which
, portp
, (portp
? *portp
: 0));
516 #endif /* MACH_ASSERT */
519 return KERN_INVALID_ARGUMENT
;
520 thread
= act_lock_thread(thr_act
);
522 case THREAD_KERNEL_PORT
:
523 whichp
= &thr_act
->ith_sself
;
527 act_unlock_thread(thr_act
);
528 return KERN_INVALID_ARGUMENT
;
531 if (!thr_act
->active
) {
532 act_unlock_thread(thr_act
);
536 port
= ipc_port_copy_send(*whichp
);
537 act_unlock_thread(thr_act
);
544 * Routine: thread_set_special_port [kernel call]
546 * Changes one of the thread's special ports,
547 * setting it to the supplied send right.
549 * Nothing locked. If successful, consumes
550 * the supplied send right.
552 * KERN_SUCCESS Changed the special port.
553 * KERN_INVALID_ARGUMENT The thread is null.
554 * KERN_FAILURE The thread is dead.
555 * KERN_INVALID_ARGUMENT Invalid special port.
559 thread_set_special_port(
560 thread_act_t thr_act
,
569 if (watchacts
& WA_PORT
)
570 printf("thread_set_special_port(thr_act=%x,which=%x,port=%x\n",
571 thr_act
, which
, port
);
572 #endif /* MACH_ASSERT */
575 return KERN_INVALID_ARGUMENT
;
577 thread
= act_lock_thread(thr_act
);
579 case THREAD_KERNEL_PORT
:
580 whichp
= &thr_act
->ith_self
;
584 act_unlock_thread(thr_act
);
585 return KERN_INVALID_ARGUMENT
;
588 if (!thr_act
->active
) {
589 act_unlock_thread(thr_act
);
595 act_unlock_thread(thr_act
);
598 ipc_port_release_send(old
);
603 * thread state should always be accessible by locking the thread
604 * and copying it. The activation messes things up so for right
605 * now if it's not the top of the chain, use a special handler to
606 * get the information when the shuttle returns to the activation.
610 register thread_act_t act
,
612 thread_state_t state
, /* pointer to OUT array */
613 mach_msg_type_number_t
*state_count
) /*IN/OUT*/
615 kern_return_t result
= KERN_SUCCESS
;
618 if (act
== THR_ACT_NULL
|| act
== current_act())
619 return (KERN_INVALID_ARGUMENT
);
621 thread
= act_lock_thread(act
);
624 act_unlock_thread(act
);
625 return (KERN_TERMINATED
);
633 if ( thread
== THREAD_NULL
||
634 thread
->top_act
!= act
)
636 act_unlock_thread(act
);
638 if (!thread_stop(thread
)) {
639 result
= KERN_ABORTED
;
640 (void)act_lock_thread(act
);
641 thread
= THREAD_NULL
;
645 thread1
= act_lock_thread(act
);
646 if (thread1
== thread
)
649 thread_unstop(thread
);
653 if (result
== KERN_SUCCESS
)
654 result
= act_machine_get_state(act
, flavor
, state
, state_count
);
656 if ( thread
!= THREAD_NULL
&&
657 thread
->top_act
== act
)
658 thread_unstop(thread
);
661 act_unlock_thread(act
);
667 * Change thread's machine-dependent state. Called with nothing
668 * locked. Returns same way.
672 register thread_act_t act
,
674 thread_state_t state
,
675 mach_msg_type_number_t state_count
)
677 kern_return_t result
= KERN_SUCCESS
;
680 if (act
== THR_ACT_NULL
|| act
== current_act())
681 return (KERN_INVALID_ARGUMENT
);
683 thread
= act_lock_thread(act
);
686 act_unlock_thread(act
);
687 return (KERN_TERMINATED
);
695 if ( thread
== THREAD_NULL
||
696 thread
->top_act
!= act
)
698 act_unlock_thread(act
);
700 if (!thread_stop(thread
)) {
701 result
= KERN_ABORTED
;
702 (void)act_lock_thread(act
);
703 thread
= THREAD_NULL
;
707 thread1
= act_lock_thread(act
);
708 if (thread1
== thread
)
711 thread_unstop(thread
);
715 if (result
== KERN_SUCCESS
)
716 result
= act_machine_set_state(act
, flavor
, state
, state_count
);
718 if ( thread
!= THREAD_NULL
&&
719 thread
->top_act
== act
)
720 thread_unstop(thread
);
723 act_unlock_thread(act
);
729 * Kernel-internal "thread" interfaces used outside this file:
734 register thread_act_t target
)
736 kern_return_t result
= KERN_SUCCESS
;
737 thread_act_t self
= current_act();
740 if (target
== THR_ACT_NULL
|| target
== self
)
741 return (KERN_INVALID_ARGUMENT
);
743 thread
= act_lock_thread(target
);
745 if (!target
->active
) {
746 act_unlock_thread(target
);
747 return (KERN_TERMINATED
);
755 if ( thread
== THREAD_NULL
||
756 thread
->top_act
!= target
)
758 act_unlock_thread(target
);
760 if (!thread_stop(thread
)) {
761 result
= KERN_ABORTED
;
762 (void)act_lock_thread(target
);
763 thread
= THREAD_NULL
;
767 thread1
= act_lock_thread(target
);
768 if (thread1
== thread
)
771 thread_unstop(thread
);
775 if (result
== KERN_SUCCESS
)
776 result
= act_thread_dup(self
, target
);
778 if ( thread
!= THREAD_NULL
&&
779 thread
->top_act
== target
)
780 thread_unstop(thread
);
782 thread_release(target
);
783 act_unlock_thread(target
);
792 * Set the status of the specified thread.
793 * Called with (and returns with) no locks held.
797 register thread_act_t act
,
799 thread_state_t tstate
,
800 mach_msg_type_number_t count
)
802 kern_return_t result
= KERN_SUCCESS
;
805 thread
= act_lock_thread(act
);
807 if ( act
!= current_act() &&
808 (act
->suspend_count
== 0 ||
809 thread
== THREAD_NULL
||
810 (thread
->state
& TH_RUN
) ||
811 thread
->top_act
!= act
) )
812 result
= KERN_FAILURE
;
814 if (result
== KERN_SUCCESS
)
815 result
= act_machine_set_state(act
, flavor
, tstate
, count
);
817 act_unlock_thread(act
);
825 * Get the status of the specified thread.
829 register thread_act_t act
,
831 thread_state_t tstate
,
832 mach_msg_type_number_t
*count
)
834 kern_return_t result
= KERN_SUCCESS
;
837 thread
= act_lock_thread(act
);
839 if ( act
!= current_act() &&
840 (act
->suspend_count
== 0 ||
841 thread
== THREAD_NULL
||
842 (thread
->state
& TH_RUN
) ||
843 thread
->top_act
!= act
) )
844 result
= KERN_FAILURE
;
846 if (result
== KERN_SUCCESS
)
847 result
= act_machine_get_state(act
, flavor
, tstate
, count
);
849 act_unlock_thread(act
);
855 * Kernel-internal thread_activation interfaces used outside this file:
859 * act_init() - Initialize activation handling code
864 thr_act_zone
= zinit(
865 sizeof(struct thread_activation
),
866 ACT_MAX
* sizeof(struct thread_activation
), /* XXX */
867 ACT_CHUNK
* sizeof(struct thread_activation
),
875 * act_create - Create a new activation in a specific task.
878 act_create(task_t task
,
879 thread_act_t
*new_act
)
881 thread_act_t thr_act
;
886 thr_act
= &pageout_act
;
889 thr_act
= (thread_act_t
)zalloc(thr_act_zone
);
891 return(KERN_RESOURCE_SHORTAGE
);
894 if (watchacts
& WA_ACT_LNK
)
895 printf("act_create(task=%x,thr_act@%x=%x)\n",
896 task
, new_act
, thr_act
);
897 #endif /* MACH_ASSERT */
899 /* Start by zeroing everything; then init non-zero items only */
900 bzero((char *)thr_act
, sizeof(*thr_act
));
902 if (thr_act
== &pageout_act
)
903 thr_act
->thread
= &pageout_thread
;
908 * Take care of the uthread allocation
909 * do it early in order to make KERN_RESOURCE_SHORTAGE
911 * uthread_alloc() will bzero the storage allocated.
913 extern void *uthread_alloc(task_t
, thread_act_t
);
915 thr_act
->uthread
= uthread_alloc(task
, thr_act
);
916 if(thr_act
->uthread
== 0) {
917 /* Put the thr_act back on the thr_act zone */
918 zfree(thr_act_zone
, (vm_offset_t
)thr_act
);
919 return(KERN_RESOURCE_SHORTAGE
);
922 #endif /* MACH_BSD */
925 * Start with one reference for the caller and one for the
928 act_lock_init(thr_act
);
929 thr_act
->ref_count
= 2;
931 /* Latch onto the task. */
932 thr_act
->task
= task
;
933 task_reference(task
);
935 /* special_handler will always be last on the returnhandlers list. */
936 thr_act
->special_handler
.next
= 0;
937 thr_act
->special_handler
.handler
= special_handler
;
940 thr_act
->act_profiled
= FALSE
;
941 thr_act
->act_profiled_own
= FALSE
;
942 thr_act
->profil_buffer
= NULLPROFDATA
;
945 /* Initialize the held_ulocks queue as empty */
946 queue_init(&thr_act
->held_ulocks
);
948 /* Inherit the profiling status of the parent task */
949 act_prof_init(thr_act
, task
);
951 ipc_thr_act_init(task
, thr_act
);
952 act_machine_create(task
, thr_act
);
955 * If thr_act created in kernel-loaded task, alter its saved
956 * state to so indicate
958 if (task
->kernel_loaded
) {
959 act_user_to_kernel(thr_act
);
962 /* Cache the task's map and take a reference to it */
966 /* Inline vm_map_reference cause we don't want to increment res_count */
967 mutex_lock(&map
->s_lock
);
969 mutex_unlock(&map
->s_lock
);
976 * act_free - called when an thr_act's ref_count drops to zero.
978 * This can only happen after the activation has been reaped, and
979 * all other references to it have gone away. We can now release
980 * the last critical resources, unlink the activation from the
981 * task, and release the reference on the thread shuttle itself.
983 * Called with activation locked.
986 int dangerous_bzero
= 1; /* paranoia & safety */
990 act_free(thread_act_t thr_act
)
999 if (watchacts
& WA_EXIT
)
1000 printf("act_free(%x(%d)) thr=%x tsk=%x(%d) %sactive\n",
1001 thr_act
, thr_act
->ref_count
, thr_act
->thread
,
1003 thr_act
->task
? thr_act
->task
->ref_count
: 0,
1004 thr_act
->active
? " " : " !");
1005 #endif /* MACH_ASSERT */
1007 assert(!thr_act
->active
);
1009 task
= thr_act
->task
;
1012 task_proc
= task
->bsd_info
;
1013 if (thr
= thr_act
->thread
) {
1014 time_value_t user_time
, system_time
;
1016 thread_read_times(thr
, &user_time
, &system_time
);
1017 time_value_add(&task
->total_user_time
, &user_time
);
1018 time_value_add(&task
->total_system_time
, &system_time
);
1020 /* Unlink the thr_act from the task's thr_act list,
1021 * so it doesn't appear in calls to task_threads and such.
1022 * The thr_act still keeps its ref on the task, however.
1024 queue_remove(&task
->thr_acts
, thr_act
, thread_act_t
, thr_acts
);
1025 thr_act
->thr_acts
.next
= NULL
;
1026 task
->thr_act_count
--;
1027 task
->res_act_count
--;
1029 task_deallocate(task
);
1030 thread_deallocate(thr
);
1031 act_machine_destroy(thr_act
);
1034 * Must have never really gotten started
1035 * no unlinking from the task and no need
1036 * to free the shuttle.
1039 task_deallocate(task
);
1042 act_prof_deallocate(thr_act
);
1043 ipc_thr_act_terminate(thr_act
);
1046 * Drop the cached map reference.
1047 * Inline version of vm_map_deallocate() because we
1048 * don't want to decrement the map's residence count here.
1051 mutex_lock(&map
->s_lock
);
1052 ref
= --map
->ref_count
;
1053 mutex_unlock(&map
->s_lock
);
1055 vm_map_destroy(map
);
1060 * Free uthread BEFORE the bzero.
1061 * Not doing so will result in a leak.
1063 extern void uthread_free(task_t
, void *, void *);
1065 void *ut
= thr_act
->uthread
;
1066 thr_act
->uthread
= 0;
1067 uthread_free(task
, ut
, task_proc
);
1069 #endif /* MACH_BSD */
1072 if (dangerous_bzero
) /* dangerous if we're still using it! */
1073 bzero((char *)thr_act
, sizeof(*thr_act
));
1074 #endif /* MACH_ASSERT */
1075 /* Put the thr_act back on the thr_act zone */
1076 zfree(thr_act_zone
, (vm_offset_t
)thr_act
);
1081 * act_attach - Attach an thr_act to the top of a thread ("push the stack").
1083 * The thread_shuttle must be either the current one or a brand-new one.
1084 * Assumes the thr_act is active but not in use.
1086 * Already locked: thr_act plus "appropriate" thread-related locks
1087 * (see act_lock_thread()).
1091 thread_act_t thr_act
,
1093 unsigned init_alert_mask
)
1098 assert(thread
== current_thread() || thread
->top_act
== THR_ACT_NULL
);
1099 if (watchacts
& WA_ACT_LNK
)
1100 printf("act_attach(thr_act %x(%d) thread %x(%d) mask %d)\n",
1101 thr_act
, thr_act
->ref_count
, thread
, thread
->ref_count
,
1103 #endif /* MACH_ASSERT */
1106 * Chain the thr_act onto the thread's thr_act stack.
1107 * Set mask and auto-propagate alerts from below.
1109 thr_act
->ref_count
++;
1110 thr_act
->thread
= thread
;
1111 thr_act
->higher
= THR_ACT_NULL
; /*safety*/
1112 thr_act
->alerts
= 0;
1113 thr_act
->alert_mask
= init_alert_mask
;
1114 lower
= thr_act
->lower
= thread
->top_act
;
1116 if (lower
!= THR_ACT_NULL
) {
1117 lower
->higher
= thr_act
;
1118 thr_act
->alerts
= (lower
->alerts
& init_alert_mask
);
1121 thread
->top_act
= thr_act
;
1127 * Remove the current thr_act from the top of the current thread, i.e.
1128 * "pop the stack". Assumes already locked: thr_act plus "appropriate"
1129 * thread-related locks (see act_lock_thread).
1133 thread_act_t cur_act
)
1135 thread_t cur_thread
= cur_act
->thread
;
1138 if (watchacts
& (WA_EXIT
|WA_ACT_LNK
))
1139 printf("act_detach: thr_act %x(%d), thrd %x(%d) task=%x(%d)\n",
1140 cur_act
, cur_act
->ref_count
,
1141 cur_thread
, cur_thread
->ref_count
,
1143 cur_act
->task
? cur_act
->task
->ref_count
: 0);
1144 #endif /* MACH_ASSERT */
1146 /* Unlink the thr_act from the thread's thr_act stack */
1147 cur_thread
->top_act
= cur_act
->lower
;
1148 cur_act
->thread
= 0;
1149 cur_act
->ref_count
--;
1150 assert(cur_act
->ref_count
> 0);
1153 cur_act
->lower
= cur_act
->higher
= THR_ACT_NULL
;
1154 if (cur_thread
->top_act
)
1155 cur_thread
->top_act
->higher
= THR_ACT_NULL
;
1156 #endif /* MACH_ASSERT */
1163 * Synchronize a thread operation with migration.
1164 * Called with nothing locked.
1165 * Returns with thr_act locked.
1169 thread_act_t thr_act
)
1173 * JMM - We have moved away from explicit RPC locks
1174 * and towards a generic migration approach. The wait
1175 * queue lock will be the point of synchronization for
1176 * the shuttle linkage when this is rolled out. Until
1177 * then, just lock the act.
1180 return (thr_act
->thread
);
1184 * Unsynchronize with migration (i.e., undo an act_lock_thread() call).
1185 * Called with thr_act locked, plus thread locks held that are
1186 * "correct" for thr_act's state. Returns with nothing locked.
1189 act_unlock_thread(thread_act_t thr_act
)
1191 act_unlock(thr_act
);
1195 * Synchronize with migration given a pointer to a shuttle (instead of an
1196 * activation). Called with nothing locked; returns with all
1197 * "appropriate" thread-related locks held (see act_lock_thread()).
1203 thread_act_t thr_act
;
1206 thr_act
= thread
->top_act
;
1209 if (!act_lock_try(thr_act
)) {
1219 * Unsynchronize with an activation starting from a pointer to
1226 thread_act_t thr_act
;
1228 if (thr_act
= thread
->top_act
) {
1229 act_unlock(thr_act
);
1236 * If a new activation is given, switch to it. If not,
1237 * switch to the lower activation (pop). Returns the old
1238 * activation. This is for migration support.
1245 thread_act_t old
, new;
1250 disable_preemption();
1253 thread
= current_thread();
1256 * Find the old and new activation for switch.
1258 old
= thread
->top_act
;
1262 new->thread
= thread
;
1268 assert(new != THR_ACT_NULL
);
1269 assert(cpu_to_processor(cpu
)->cpu_data
->active_thread
== thread
);
1270 active_kloaded
[cpu
] = (new->kernel_loaded
) ? new : 0;
1272 /* This is where all the work happens */
1273 machine_switch_act(thread
, old
, new, cpu
);
1276 * Push or pop an activation on the chain.
1279 act_attach(new, thread
, 0);
1285 enable_preemption();
1291 * install_special_handler
1292 * Install the special returnhandler that handles suspension and
1293 * termination, if it hasn't been installed already.
1295 * Already locked: RPC-related locks for thr_act, but not
1296 * scheduling lock (thread_lock()) of the associated thread.
1299 install_special_handler(
1300 thread_act_t thr_act
)
1303 thread_t thread
= thr_act
->thread
;
1306 if (watchacts
& WA_ACT_HDLR
)
1307 printf("act_%x: install_special_hdlr(%x)\n",current_act(),thr_act
);
1308 #endif /* MACH_ASSERT */
1311 thread_lock(thread
);
1312 install_special_handler_locked(thr_act
);
1313 thread_unlock(thread
);
1318 * install_special_handler_locked
1319 * Do the work of installing the special_handler.
1321 * Already locked: RPC-related locks for thr_act, plus the
1322 * scheduling lock (thread_lock()) of the associated thread.
1325 install_special_handler_locked(
1328 thread_t thread
= act
->thread
;
1331 /* The work handler must always be the last ReturnHandler on the list,
1332 because it can do tricky things like detach the thr_act. */
1333 for (rh
= &act
->handlers
; *rh
; rh
= &(*rh
)->next
)
1335 if (rh
!= &act
->special_handler
.next
)
1336 *rh
= &act
->special_handler
;
1338 if (act
== thread
->top_act
) {
1340 * Temporarily undepress, so target has
1341 * a chance to do locking required to
1342 * block itself in special_handler().
1344 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
)
1345 compute_priority(thread
, TRUE
);
1348 thread_ast_set(act
, AST_APC
);
1349 if (act
== current_act())
1350 ast_propagate(act
->ast
);
1352 processor_t processor
= thread
->last_processor
;
1354 if ( processor
!= PROCESSOR_NULL
&&
1355 processor
->state
== PROCESSOR_RUNNING
&&
1356 processor
->cpu_data
->active_thread
== thread
)
1357 cause_ast_check(processor
);
1364 thread_apc_handler_t apc
)
1366 extern thread_apc_handler_t bsd_ast
;
1368 assert(apc
== bsd_ast
);
1369 return (KERN_FAILURE
);
1375 thread_apc_handler_t apc
)
1377 extern thread_apc_handler_t bsd_ast
;
1379 assert(apc
== bsd_ast
);
1380 return (KERN_FAILURE
);
1384 * Activation control support routines internal to this file:
1388 * act_execute_returnhandlers() - does just what the name says
1390 * This is called by system-dependent code when it detects that
1391 * thr_act->handlers is non-null while returning into user mode.
1394 act_execute_returnhandlers(void)
1396 thread_act_t act
= current_act();
1399 if (watchacts
& WA_ACT_HDLR
)
1400 printf("execute_rtn_hdlrs: act=%x\n", act
);
1401 #endif /* MACH_ASSERT */
1403 thread_ast_clear(act
, AST_APC
);
1408 thread_t thread
= act_lock_thread(act
);
1411 thread_lock(thread
);
1414 thread_unlock(thread
);
1416 act_unlock_thread(act
);
1419 act
->handlers
= rh
->next
;
1420 thread_unlock(thread
);
1422 act_unlock_thread(act
);
1425 if (watchacts
& WA_ACT_HDLR
)
1426 printf( (rh
== &act
->special_handler
) ?
1427 "\tspecial_handler\n" : "\thandler=%x\n", rh
->handler
);
1428 #endif /* MACH_ASSERT */
1431 (*rh
->handler
)(rh
, act
);
1436 * special_handler_continue
1438 * Continuation routine for the special handler blocks. It checks
1439 * to see whether there has been any new suspensions. If so, it
1440 * installs the special handler again. Otherwise, it checks to see
1441 * if the current depression needs to be re-instated (it may have
1442 * been temporarily removed in order to get to this point in a hurry).
1445 special_handler_continue(void)
1447 thread_act_t self
= current_act();
1449 if (self
->suspend_count
> 0)
1450 install_special_handler(self
);
1452 thread_t thread
= self
->thread
;
1453 spl_t s
= splsched();
1455 thread_lock(thread
);
1456 if (thread
->sched_mode
& TH_MODE_ISDEPRESSED
) {
1457 processor_t myprocessor
= thread
->last_processor
;
1459 thread
->sched_pri
= DEPRESSPRI
;
1460 myprocessor
->current_pri
= thread
->sched_pri
;
1461 thread
->sched_mode
&= ~TH_MODE_PREEMPT
;
1463 thread_unlock(thread
);
1467 thread_exception_return();
1472 * special_handler - handles suspension, termination. Called
1473 * with nothing locked. Returns (if it returns) the same way.
1480 thread_t thread
= act_lock_thread(self
);
1483 assert(thread
!= THREAD_NULL
);
1486 thread_lock(thread
);
1487 thread
->state
&= ~(TH_ABORT
|TH_ABORT_SAFELY
); /* clear any aborts */
1488 thread_unlock(thread
);
1492 * If someone has killed this invocation,
1493 * invoke the return path with a terminated exception.
1495 if (!self
->active
) {
1496 act_unlock_thread(self
);
1497 act_machine_return(KERN_TERMINATED
);
1501 * If we're suspended, go to sleep and wait for someone to wake us up.
1503 if (self
->suspend_count
> 0) {
1504 if (self
->handlers
== NULL
) {
1505 assert_wait(&self
->suspend_count
, THREAD_ABORTSAFE
);
1506 act_unlock_thread(self
);
1507 thread_block(special_handler_continue
);
1511 act_unlock_thread(self
);
1513 special_handler_continue();
1517 act_unlock_thread(self
);
1521 * Update activation that belongs to a task created via kernel_task_create().
1525 thread_act_t thr_act
)
1527 pcb_user_to_kernel(thr_act
);
1528 thr_act
->kernel_loading
= TRUE
;
1532 * Already locked: activation (shuttle frozen within)
1534 * Mark an activation inactive, and prepare it to terminate
1539 thread_act_t thr_act
)
1543 if (watchacts
& WA_EXIT
) {
1544 printf("act_%x: act_disable_tl(thr_act=%x(%d))%sactive",
1545 current_act(), thr_act
, thr_act
->ref_count
,
1546 (thr_act
->active
? " " : " !"));
1548 (void) dump_act(thr_act
);
1550 #endif /* MACH_ASSERT */
1552 thr_act
->active
= 0;
1554 /* Drop the thr_act reference taken for being active.
1555 * (There is still at least one reference left:
1556 * the one we were passed.)
1557 * Inline the deallocate because thr_act is locked.
1559 act_locked_act_deallocate(thr_act
);
1563 * act_alert - Register an alert from this activation.
1565 * Each set bit is propagated upward from (but not including) this activation,
1566 * until the top of the chain is reached or the bit is masked.
1569 act_alert(thread_act_t thr_act
, unsigned alerts
)
1571 thread_t thread
= act_lock_thread(thr_act
);
1574 if (watchacts
& WA_ACT_LNK
)
1575 printf("act_alert %x: %x\n", thr_act
, alerts
);
1576 #endif /* MACH_ASSERT */
1579 thread_act_t act_up
= thr_act
;
1580 while ((alerts
) && (act_up
!= thread
->top_act
)) {
1581 act_up
= act_up
->higher
;
1582 alerts
&= act_up
->alert_mask
;
1583 act_up
->alerts
|= alerts
;
1586 * XXXX If we reach the top, and it is blocked in glue
1587 * code, do something to kick it. XXXX
1590 act_unlock_thread(thr_act
);
1592 return KERN_SUCCESS
;
1595 kern_return_t
act_alert_mask(thread_act_t thr_act
, unsigned alert_mask
)
1597 panic("act_alert_mask NOT YET IMPLEMENTED\n");
1598 return KERN_SUCCESS
;
1601 typedef struct GetSetState
{
1602 struct ReturnHandler rh
;
1609 /* Local Forward decls */
1610 kern_return_t
get_set_state(
1611 thread_act_t thr_act
, int flavor
,
1612 thread_state_t state
, int *pcount
,
1613 void (*handler
)(ReturnHandler
*rh
, thread_act_t thr_act
));
1614 void get_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
);
1615 void set_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
);
1618 * get_set_state(thr_act ...)
1620 * General code to install g/set_state handler.
1621 * Called with thr_act's act_lock() and "appropriate"
1622 * thread-related locks held. (See act_lock_thread().)
1628 thread_state_t state
,
1636 /* Initialize a small parameter structure */
1637 gss
.rh
.handler
= handler
;
1638 gss
.flavor
= flavor
;
1640 gss
.pcount
= pcount
;
1641 gss
.result
= KERN_ABORTED
; /* iff wait below is interrupted */
1643 /* Add it to the thr_act's return handler list */
1644 gss
.rh
.next
= act
->handlers
;
1645 act
->handlers
= &gss
.rh
;
1650 if (watchacts
& WA_ACT_HDLR
) {
1651 printf("act_%x: get_set_state(act=%x flv=%x state=%x ptr@%x=%x)",
1652 current_act(), act
, flavor
, state
,
1653 pcount
, (pcount
? *pcount
: 0));
1654 printf((handler
== get_state_handler
? "get_state_hdlr\n" :
1655 (handler
== set_state_handler
? "set_state_hdlr\n" :
1656 "hndler=%x\n")), handler
);
1658 #endif /* MACH_ASSERT */
1660 assert(act
->thread
);
1661 assert(act
!= current_act());
1664 wait_result_t result
;
1667 act
->thread
->top_act
== act
)
1668 thread_wakeup_one(&act
->suspend_count
);
1671 * Wait must be interruptible to avoid deadlock (e.g.) with
1672 * task_suspend() when caller and target of get_set_state()
1675 result
= assert_wait(&gss
, THREAD_ABORTSAFE
);
1676 act_unlock_thread(act
);
1678 if (result
== THREAD_WAITING
)
1679 result
= thread_block(THREAD_CONTINUE_NULL
);
1681 assert(result
!= THREAD_WAITING
);
1683 if (gss
.result
!= KERN_ABORTED
) {
1684 assert(result
!= THREAD_INTERRUPTED
);
1688 /* JMM - What about other aborts (like BSD signals)? */
1689 if (current_act()->handlers
)
1690 act_execute_returnhandlers();
1692 act_lock_thread(act
);
1696 if (watchacts
& WA_ACT_HDLR
)
1697 printf("act_%x: get_set_state returns %x\n",
1698 current_act(), gss
.result
);
1699 #endif /* MACH_ASSERT */
1701 return (gss
.result
);
1705 set_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
)
1707 GetSetState
*gss
= (GetSetState
*)rh
;
1710 if (watchacts
& WA_ACT_HDLR
)
1711 printf("act_%x: set_state_handler(rh=%x,thr_act=%x)\n",
1712 current_act(), rh
, thr_act
);
1713 #endif /* MACH_ASSERT */
1715 gss
->result
= act_machine_set_state(thr_act
, gss
->flavor
,
1716 gss
->state
, *gss
->pcount
);
1717 thread_wakeup((event_t
)gss
);
1721 get_state_handler(ReturnHandler
*rh
, thread_act_t thr_act
)
1723 GetSetState
*gss
= (GetSetState
*)rh
;
1726 if (watchacts
& WA_ACT_HDLR
)
1727 printf("act_%x: get_state_handler(rh=%x,thr_act=%x)\n",
1728 current_act(), rh
, thr_act
);
1729 #endif /* MACH_ASSERT */
1731 gss
->result
= act_machine_get_state(thr_act
, gss
->flavor
,
1733 (mach_msg_type_number_t
*) gss
->pcount
);
1734 thread_wakeup((event_t
)gss
);
1738 act_get_state_locked(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1739 mach_msg_type_number_t
*pcount
)
1742 if (watchacts
& WA_ACT_HDLR
)
1743 printf("act_%x: act_get_state_L(thr_act=%x,flav=%x,st=%x,pcnt@%x=%x)\n",
1744 current_act(), thr_act
, flavor
, state
, pcount
,
1745 (pcount
? *pcount
: 0));
1746 #endif /* MACH_ASSERT */
1748 return(get_set_state(thr_act
, flavor
, state
, (int*)pcount
, get_state_handler
));
1752 act_set_state_locked(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1753 mach_msg_type_number_t count
)
1756 if (watchacts
& WA_ACT_HDLR
)
1757 printf("act_%x: act_set_state_L(thr_act=%x,flav=%x,st=%x,pcnt@%x=%x)\n",
1758 current_act(), thr_act
, flavor
, state
, count
, count
);
1759 #endif /* MACH_ASSERT */
1761 return(get_set_state(thr_act
, flavor
, state
, (int*)&count
, set_state_handler
));
1765 act_set_state(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1766 mach_msg_type_number_t count
)
1768 if (thr_act
== THR_ACT_NULL
|| thr_act
== current_act())
1769 return(KERN_INVALID_ARGUMENT
);
1771 act_lock_thread(thr_act
);
1772 return(act_set_state_locked(thr_act
, flavor
, state
, count
));
1777 act_get_state(thread_act_t thr_act
, int flavor
, thread_state_t state
,
1778 mach_msg_type_number_t
*pcount
)
1780 if (thr_act
== THR_ACT_NULL
|| thr_act
== current_act())
1781 return(KERN_INVALID_ARGUMENT
);
1783 act_lock_thread(thr_act
);
1784 return(act_get_state_locked(thr_act
, flavor
, state
, pcount
));
1791 spl_t s
= splsched();
1793 if (act
== current_act()) {
1794 thread_ast_set(act
, AST_BSD
);
1795 ast_propagate(act
->ast
);
1798 thread_t thread
= act
->thread
;
1799 processor_t processor
;
1801 thread_lock(thread
);
1802 thread_ast_set(act
, AST_BSD
);
1803 processor
= thread
->last_processor
;
1804 if ( processor
!= PROCESSOR_NULL
&&
1805 processor
->state
== PROCESSOR_RUNNING
&&
1806 processor
->cpu_data
->active_thread
== thread
)
1807 cause_ast_check(processor
);
1808 thread_unlock(thread
);
1818 spl_t s
= splsched();
1820 if (act
== current_act()) {
1821 thread_ast_set(act
, AST_APC
);
1822 ast_propagate(act
->ast
);
1825 thread_t thread
= act
->thread
;
1826 processor_t processor
;
1828 thread_lock(thread
);
1829 thread_ast_set(act
, AST_APC
);
1830 processor
= thread
->last_processor
;
1831 if ( processor
!= PROCESSOR_NULL
&&
1832 processor
->state
== PROCESSOR_RUNNING
&&
1833 processor
->cpu_data
->active_thread
== thread
)
1834 cause_ast_check(processor
);
1835 thread_unlock(thread
);
1842 act_ulock_release_all(thread_act_t thr_act
)
1846 while (!queue_empty(&thr_act
->held_ulocks
)) {
1847 ulock
= (ulock_t
) queue_first(&thr_act
->held_ulocks
);
1848 (void) lock_make_unstable(ulock
, thr_act
);
1849 (void) lock_release_internal(ulock
, thr_act
);
1854 * Provide routines (for export to other components) of things that
1855 * are implemented as macros insternally.
1860 thread_act_t self
= current_act_fast();
1862 act_reference(self
);
1867 mach_thread_self(void)
1869 thread_act_t self
= current_act_fast();
1871 act_reference(self
);
1875 #undef act_reference
1878 thread_act_t thr_act
)
1880 act_reference_fast(thr_act
);
1883 #undef act_deallocate
1886 thread_act_t thr_act
)
1888 act_deallocate_fast(thr_act
);