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 Computer Systems Laboratory (CSL). 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 CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
39 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
40 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
42 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
43 * improvements that they make and grant CSL redistribution rights.
45 * Author: Bryan Ford, University of Utah CSL
49 * thread activation definitions
51 #ifndef _KERN_THREAD_ACT_H_
52 #define _KERN_THREAD_ACT_H_
54 #include <mach/mach_types.h>
55 #include <mach/vm_param.h>
56 #include <mach/thread_info.h>
57 #include <mach/exception_types.h>
59 #include <sys/appleapiopts.h>
61 #ifdef __APPLE_API_PRIVATE
63 #ifdef MACH_KERNEL_PRIVATE
65 #include <mach_assert.h>
66 #include <thread_swapper.h>
69 #include <kern/lock.h>
70 #include <kern/queue.h>
71 #include <kern/etap_macros.h>
72 #include <kern/exception.h>
73 #include <kern/thread.h>
74 #include <ipc/ipc_port.h>
75 #include <machine/thread_act.h>
78 * Here is a description of the states an thread_activation may be in.
80 * An activation always has a valid task pointer, and it is always constant.
81 * The activation is only linked onto the task's activation list until
82 * the activation is terminated.
84 * The thread holds a reference on the activation while using it.
86 * An activation is active until thread_terminate is called on it;
87 * then it is inactive, waiting for all references to be dropped.
88 * Future control operations on the terminated activation will fail,
89 * with the exception that act_yank still works if the activation is
90 * still on an RPC chain. A terminated activation always has a null
93 * An activation is suspended when suspend_count > 0.
95 * Locking note: access to data relevant to scheduling state (user_stop_count,
96 * suspend_count, handlers, special_handler) is controlled by the combination
97 * of locks acquired by act_lock_thread(). That is, not only must act_lock()
98 * be held, but migration through the activation must be frozen (so that the
99 * thread pointer doesn't change). If a shuttle is associated with the
100 * activation, then its thread_lock() must also be acquired to change these
101 * data. Regardless of whether a shuttle is present, the data must be
102 * altered at splsched().
105 typedef struct ReturnHandler
{
106 struct ReturnHandler
*next
;
107 void (*handler
)(struct ReturnHandler
*rh
,
108 struct thread_activation
*thr_act
);
111 typedef struct thread_activation
{
113 /*** task linkage ***/
115 /* Links for task's circular list of activations. The activation
116 * is only on the task's activation list while active. Must be
119 queue_chain_t thr_acts
;
121 /* Indicators for whether this activation is in the midst of
122 * resuming or has already been resumed in a kernel-loaded
123 * task -- these flags are basically for quick access to
126 boolean_t kernel_loaded
; /* running in kernel-loaded task */
127 boolean_t kernel_loading
; /* about to run kernel-loaded */
131 /*** Machine-dependent state ***/
132 struct MachineThrAct mact
;
134 /*** Consistency ***/
135 decl_mutex_data(,lock
)
136 decl_simple_lock_data(,sched_lock
)
139 /* Reference to the task this activation is in.
140 * Constant for the life of the activation
143 vm_map_t map
; /* cached current map */
145 /*** Thread linkage ***/
146 /* Shuttle using this activation, zero if not in use. The shuttle
147 * holds a reference on the activation while this is nonzero.
149 struct thread_shuttle
*thread
;
151 /* The rest in this section is only valid when thread is nonzero. */
153 /* Next higher and next lower activation on the thread's activation
154 * stack. For a topmost activation or the null_act, higher is
155 * undefined. The bottommost activation is always the null_act.
157 struct thread_activation
*higher
, *lower
;
159 /* Alert bits pending at this activation; some of them may have
160 * propagated from lower activations.
164 /* Mask of alert bits to be allowed to pass through from lower levels.
168 /*** Control information ***/
170 /* Number of outstanding suspensions on this activation. */
173 /* User-visible scheduling state */
174 int user_stop_count
; /* outstanding stops */
176 /* ast is needed - see ast.h */
179 /* This is normally true, but is set to false when the
180 * activation is terminated.
184 /* Chain of return handlers to be called before the thread is
185 * allowed to return to this invocation
187 ReturnHandler
*handlers
;
189 /* A special ReturnHandler attached to the above chain to
190 * handle suspension and such
192 ReturnHandler special_handler
;
194 /* Special ports attached to this activation */
195 struct ipc_port
*ith_self
; /* not a right, doesn't hold ref */
196 struct ipc_port
*ith_sself
; /* a send right */
197 struct exception_action exc_actions
[EXC_TYPES_COUNT
];
199 /* A list of ulocks (a lock set element) currently held by the thread
201 queue_head_t held_ulocks
;
204 /* Profiling data structures */
205 boolean_t act_profiled
; /* is activation being profiled? */
206 boolean_t act_profiled_own
;
207 /* is activation being profiled
209 struct prof_data
*profil_buffer
;/* prof struct if either is so */
210 #endif /* MACH_PROF */
219 #define SERVER_TERMINATED 0x01
220 #define ORPHANED 0x02
221 #define CLIENT_TERMINATED 0x04
222 #define TIME_CONSTRAINT_UNSATISFIED 0x08
224 #define act_lock_init(thr_act) mutex_init(&(thr_act)->lock, ETAP_THREAD_ACT)
225 #define act_lock(thr_act) mutex_lock(&(thr_act)->lock)
226 #define act_lock_try(thr_act) mutex_try(&(thr_act)->lock)
227 #define act_unlock(thr_act) mutex_unlock(&(thr_act)->lock)
229 /* Sanity check the ref count. If it is 0, we may be doubly zfreeing.
230 * If it is larger than max int, it has been corrupted, probably by being
231 * modified into an address (this is architecture dependent, but it's
232 * safe to assume there cannot really be max int references).
234 #define ACT_MAX_REFERENCES \
235 (unsigned)(~0 ^ (1 << (sizeof(int)*BYTE_SIZE - 1)))
237 #define act_reference_fast(thr_act) \
241 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
242 (thr_act)->ref_count++; \
243 act_unlock(thr_act); \
247 #define act_reference(thr_act) act_reference_fast(thr_act)
249 #define act_locked_act_reference(thr_act) \
252 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
253 (thr_act)->ref_count++; \
257 #define act_deallocate_fast(thr_act) \
262 assert((thr_act)->ref_count > 0 && \
263 (thr_act)->ref_count <= ACT_MAX_REFERENCES); \
264 new_value = --(thr_act)->ref_count; \
265 act_unlock(thr_act); \
266 if (new_value == 0) \
271 #define act_deallocate(thr_act) act_deallocate_fast(thr_act)
273 #define act_locked_act_deallocate(thr_act) \
277 assert((thr_act)->ref_count > 0 && \
278 (thr_act)->ref_count <= ACT_MAX_REFERENCES); \
279 new_value = --(thr_act)->ref_count; \
280 if (new_value == 0) { \
281 panic("a_l_act_deallocate: would free act"); \
286 extern struct thread_activation pageout_act
;
288 extern void act_init(void);
289 extern void thread_release(thread_act_t
);
290 extern kern_return_t
thread_dowait(thread_act_t
, boolean_t
);
291 extern void thread_hold(thread_act_t
);
293 extern kern_return_t
thread_get_special_port(thread_act_t
, int,
295 extern kern_return_t
thread_set_special_port(thread_act_t
, int,
297 extern thread_t
act_lock_thread(thread_act_t
);
298 extern void act_unlock_thread(thread_act_t
);
299 extern void install_special_handler(thread_act_t
);
300 extern thread_act_t
thread_lock_act(thread_t
);
301 extern void thread_unlock_act(thread_t
);
302 extern void act_attach(thread_act_t
, thread_t
, unsigned);
303 extern void act_execute_returnhandlers(void);
304 extern void act_detach(thread_act_t
);
305 extern void act_free(thread_act_t
);
307 /* machine-dependent functions */
308 extern void act_machine_return(kern_return_t
);
309 extern void act_machine_init(void);
310 extern kern_return_t
act_machine_create(struct task
*, thread_act_t
);
311 extern void act_machine_destroy(thread_act_t
);
312 extern kern_return_t
act_machine_set_state(thread_act_t
,
313 thread_flavor_t
, thread_state_t
,
314 mach_msg_type_number_t
);
315 extern kern_return_t
act_machine_get_state(thread_act_t
,
316 thread_flavor_t
, thread_state_t
,
317 mach_msg_type_number_t
*);
318 extern void act_machine_switch_pcb(thread_act_t
);
319 extern void act_virtual_machine_destroy(thread_act_t
);
321 extern kern_return_t
act_create(task_t
, thread_act_t
*);
322 extern kern_return_t
act_get_state(thread_act_t
, int, thread_state_t
,
323 mach_msg_type_number_t
*);
324 extern kern_return_t
act_set_state(thread_act_t
, int, thread_state_t
,
325 mach_msg_type_number_t
);
327 extern int dump_act(thread_act_t
); /* debugging */
331 * Debugging support - "watchacts", a patchable selective trigger
333 extern unsigned int watchacts
; /* debug printf trigger */
334 #define WA_SCHED 0x001 /* kern/sched_prim.c */
335 #define WA_THR 0x002 /* kern/thread.c */
336 #define WA_ACT_LNK 0x004 /* kern/thread_act.c act mgmt */
337 #define WA_ACT_HDLR 0x008 /* kern/thread_act.c act hldrs */
338 #define WA_TASK 0x010 /* kern/task.c */
339 #define WA_BOOT 0x020 /* bootstrap,startup.c */
340 #define WA_PCB 0x040 /* machine/pcb.c */
341 #define WA_PORT 0x080 /* ports + port sets */
342 #define WA_EXIT 0x100 /* exit path */
343 #define WA_SWITCH 0x200 /* context switch (!!) */
344 #define WA_STATE 0x400 /* get/set state (!!) */
346 #endif /* MACH_ASSERT */
348 #else /* MACH_KERNEL_PRIVATE */
350 extern void act_reference(thread_act_t
);
351 extern void act_deallocate(thread_act_t
);
353 #endif /* MACH_KERNEL_PRIVATE */
355 extern kern_return_t
act_alert(thread_act_t
, unsigned);
356 extern kern_return_t
act_alert_mask(thread_act_t
, unsigned );
357 extern kern_return_t
post_alert(thread_act_t
, unsigned);
359 typedef void (thread_apc_handler_t
)(thread_act_t
);
361 extern kern_return_t
thread_apc_set(thread_act_t
, thread_apc_handler_t
);
362 extern kern_return_t
thread_apc_clear(thread_act_t
, thread_apc_handler_t
);
364 extern vm_map_t
swap_act_map(thread_act_t
, vm_map_t
);
366 extern void *get_bsdthread_info(thread_act_t
);
367 extern void set_bsdthread_info(thread_act_t
, void *);
368 extern task_t
get_threadtask(thread_act_t
);
370 #endif /* __APPLE_API_PRIVATE */
372 #ifdef __APPLE_API_UNSTABLE
374 #if !defined(MACH_KERNEL_PRIVATE)
376 extern thread_act_t
current_act(void);
378 #endif /* MACH_KERNEL_PRIVATE */
380 #endif /* __APPLE_API_UNSTABLE */
382 extern kern_return_t
thread_abort(thread_act_t
);
383 extern kern_return_t
thread_abort_safely(thread_act_t
);
384 extern kern_return_t
thread_resume(thread_act_t
);
385 extern kern_return_t
thread_suspend(thread_act_t
);
386 extern kern_return_t
thread_terminate(thread_act_t
);
388 #endif /* _KERN_THREAD_ACT_H_ */