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 Computer Systems Laboratory (CSL). 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 CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
36 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
37 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
40 * improvements that they make and grant CSL redistribution rights.
42 * Author: Bryan Ford, University of Utah CSL
46 * thread activation definitions
48 #ifndef _KERN_THREAD_ACT_H_
49 #define _KERN_THREAD_ACT_H_
51 #include <mach/mach_types.h>
52 #include <mach/vm_param.h>
53 #include <mach/thread_info.h>
54 #include <mach/exception_types.h>
56 #include <sys/appleapiopts.h>
58 #ifdef __APPLE_API_PRIVATE
60 #ifdef MACH_KERNEL_PRIVATE
62 #include <mach_assert.h>
63 #include <thread_swapper.h>
66 #include <kern/lock.h>
67 #include <kern/queue.h>
68 #include <kern/etap_macros.h>
69 #include <kern/exception.h>
70 #include <kern/thread.h>
71 #include <ipc/ipc_port.h>
72 #include <machine/thread_act.h>
75 * Here is a description of the states an thread_activation may be in.
77 * An activation always has a valid task pointer, and it is always constant.
78 * The activation is only linked onto the task's activation list until
79 * the activation is terminated.
81 * The thread holds a reference on the activation while using it.
83 * An activation is active until thread_terminate is called on it;
84 * then it is inactive, waiting for all references to be dropped.
85 * Future control operations on the terminated activation will fail,
86 * with the exception that act_yank still works if the activation is
87 * still on an RPC chain. A terminated activation always has a null
90 * An activation is suspended when suspend_count > 0.
92 * Locking note: access to data relevant to scheduling state (user_stop_count,
93 * suspend_count, handlers, special_handler) is controlled by the combination
94 * of locks acquired by act_lock_thread(). That is, not only must act_lock()
95 * be held, but migration through the activation must be frozen (so that the
96 * thread pointer doesn't change). If a shuttle is associated with the
97 * activation, then its thread_lock() must also be acquired to change these
98 * data. Regardless of whether a shuttle is present, the data must be
99 * altered at splsched().
102 typedef struct ReturnHandler
{
103 struct ReturnHandler
*next
;
104 void (*handler
)(struct ReturnHandler
*rh
,
105 struct thread_activation
*thr_act
);
108 typedef struct thread_activation
{
110 /*** task linkage ***/
112 /* Links for task's circular list of activations. The activation
113 * is only on the task's activation list while active. Must be
116 queue_chain_t thr_acts
;
118 /* Indicators for whether this activation is in the midst of
119 * resuming or has already been resumed in a kernel-loaded
120 * task -- these flags are basically for quick access to
123 boolean_t kernel_loaded
; /* running in kernel-loaded task */
124 boolean_t kernel_loading
; /* about to run kernel-loaded */
128 /*** Machine-dependent state ***/
129 struct MachineThrAct mact
;
131 /*** Consistency ***/
132 decl_mutex_data(,lock
)
133 decl_simple_lock_data(,sched_lock
)
136 /* Reference to the task this activation is in.
137 * Constant for the life of the activation
140 vm_map_t map
; /* cached current map */
142 /*** Thread linkage ***/
143 /* Shuttle using this activation, zero if not in use. The shuttle
144 * holds a reference on the activation while this is nonzero.
146 struct thread_shuttle
*thread
;
148 /* The rest in this section is only valid when thread is nonzero. */
150 /* Next higher and next lower activation on the thread's activation
151 * stack. For a topmost activation or the null_act, higher is
152 * undefined. The bottommost activation is always the null_act.
154 struct thread_activation
*higher
, *lower
;
156 /* Alert bits pending at this activation; some of them may have
157 * propagated from lower activations.
161 /* Mask of alert bits to be allowed to pass through from lower levels.
165 /*** Control information ***/
167 /* Number of outstanding suspensions on this activation. */
170 /* User-visible scheduling state */
171 int user_stop_count
; /* outstanding stops */
173 /* ast is needed - see ast.h */
176 /* This is normally true, but is set to false when the
177 * activation is terminated.
181 /* Chain of return handlers to be called before the thread is
182 * allowed to return to this invocation
184 ReturnHandler
*handlers
;
186 /* A special ReturnHandler attached to the above chain to
187 * handle suspension and such
189 ReturnHandler special_handler
;
191 /* Special ports attached to this activation */
192 struct ipc_port
*ith_self
; /* not a right, doesn't hold ref */
193 struct ipc_port
*ith_sself
; /* a send right */
194 struct exception_action exc_actions
[EXC_TYPES_COUNT
];
196 /* A list of ulocks (a lock set element) currently held by the thread
198 queue_head_t held_ulocks
;
201 /* Profiling data structures */
202 boolean_t act_profiled
; /* is activation being profiled? */
203 boolean_t act_profiled_own
;
204 /* is activation being profiled
206 struct prof_data
*profil_buffer
;/* prof struct if either is so */
207 #endif /* MACH_PROF */
216 #define SERVER_TERMINATED 0x01
217 #define ORPHANED 0x02
218 #define CLIENT_TERMINATED 0x04
219 #define TIME_CONSTRAINT_UNSATISFIED 0x08
221 #define act_lock_init(thr_act) mutex_init(&(thr_act)->lock, ETAP_THREAD_ACT)
222 #define act_lock(thr_act) mutex_lock(&(thr_act)->lock)
223 #define act_lock_try(thr_act) mutex_try(&(thr_act)->lock)
224 #define act_unlock(thr_act) mutex_unlock(&(thr_act)->lock)
226 /* Sanity check the ref count. If it is 0, we may be doubly zfreeing.
227 * If it is larger than max int, it has been corrupted, probably by being
228 * modified into an address (this is architecture dependent, but it's
229 * safe to assume there cannot really be max int references).
231 #define ACT_MAX_REFERENCES \
232 (unsigned)(~0 ^ (1 << (sizeof(int)*BYTE_SIZE - 1)))
234 #define act_reference_fast(thr_act) \
238 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
239 (thr_act)->ref_count++; \
240 act_unlock(thr_act); \
244 #define act_reference(thr_act) act_reference_fast(thr_act)
246 #define act_locked_act_reference(thr_act) \
249 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
250 (thr_act)->ref_count++; \
254 #define act_deallocate_fast(thr_act) \
259 assert((thr_act)->ref_count > 0 && \
260 (thr_act)->ref_count <= ACT_MAX_REFERENCES); \
261 new_value = --(thr_act)->ref_count; \
262 act_unlock(thr_act); \
263 if (new_value == 0) \
268 #define act_deallocate(thr_act) act_deallocate_fast(thr_act)
270 #define act_locked_act_deallocate(thr_act) \
274 assert((thr_act)->ref_count > 0 && \
275 (thr_act)->ref_count <= ACT_MAX_REFERENCES); \
276 new_value = --(thr_act)->ref_count; \
277 if (new_value == 0) { \
278 panic("a_l_act_deallocate: would free act"); \
283 extern struct thread_activation pageout_act
;
285 extern void act_init(void);
286 extern void thread_release(thread_act_t
);
287 extern kern_return_t
thread_dowait(thread_act_t
, boolean_t
);
288 extern void thread_hold(thread_act_t
);
290 extern kern_return_t
thread_get_special_port(thread_act_t
, int,
292 extern kern_return_t
thread_set_special_port(thread_act_t
, int,
294 extern thread_t
act_lock_thread(thread_act_t
);
295 extern void act_unlock_thread(thread_act_t
);
296 extern void install_special_handler(thread_act_t
);
297 extern thread_act_t
thread_lock_act(thread_t
);
298 extern void thread_unlock_act(thread_t
);
299 extern void act_attach(thread_act_t
, thread_t
, unsigned);
300 extern void act_execute_returnhandlers(void);
301 extern void act_detach(thread_act_t
);
302 extern void act_free(thread_act_t
);
304 /* machine-dependent functions */
305 extern void act_machine_return(kern_return_t
);
306 extern void act_machine_init(void);
307 extern kern_return_t
act_machine_create(struct task
*, thread_act_t
);
308 extern void act_machine_destroy(thread_act_t
);
309 extern kern_return_t
act_machine_set_state(thread_act_t
,
310 thread_flavor_t
, thread_state_t
,
311 mach_msg_type_number_t
);
312 extern kern_return_t
act_machine_get_state(thread_act_t
,
313 thread_flavor_t
, thread_state_t
,
314 mach_msg_type_number_t
*);
315 extern void act_machine_switch_pcb(thread_act_t
);
316 extern void act_virtual_machine_destroy(thread_act_t
);
318 extern kern_return_t
act_create(task_t
, thread_act_t
*);
319 extern kern_return_t
act_get_state(thread_act_t
, int, thread_state_t
,
320 mach_msg_type_number_t
*);
321 extern kern_return_t
act_set_state(thread_act_t
, int, thread_state_t
,
322 mach_msg_type_number_t
);
324 extern int dump_act(thread_act_t
); /* debugging */
328 * Debugging support - "watchacts", a patchable selective trigger
330 extern unsigned int watchacts
; /* debug printf trigger */
331 #define WA_SCHED 0x001 /* kern/sched_prim.c */
332 #define WA_THR 0x002 /* kern/thread.c */
333 #define WA_ACT_LNK 0x004 /* kern/thread_act.c act mgmt */
334 #define WA_ACT_HDLR 0x008 /* kern/thread_act.c act hldrs */
335 #define WA_TASK 0x010 /* kern/task.c */
336 #define WA_BOOT 0x020 /* bootstrap,startup.c */
337 #define WA_PCB 0x040 /* machine/pcb.c */
338 #define WA_PORT 0x080 /* ports + port sets */
339 #define WA_EXIT 0x100 /* exit path */
340 #define WA_SWITCH 0x200 /* context switch (!!) */
341 #define WA_STATE 0x400 /* get/set state (!!) */
343 #endif /* MACH_ASSERT */
345 #else /* MACH_KERNEL_PRIVATE */
347 extern void act_reference(thread_act_t
);
348 extern void act_deallocate(thread_act_t
);
350 #endif /* MACH_KERNEL_PRIVATE */
352 extern kern_return_t
act_alert(thread_act_t
, unsigned);
353 extern kern_return_t
act_alert_mask(thread_act_t
, unsigned );
354 extern kern_return_t
post_alert(thread_act_t
, unsigned);
356 typedef void (thread_apc_handler_t
)(thread_act_t
);
358 extern kern_return_t
thread_apc_set(thread_act_t
, thread_apc_handler_t
);
359 extern kern_return_t
thread_apc_clear(thread_act_t
, thread_apc_handler_t
);
361 extern vm_map_t
swap_act_map(thread_act_t
, vm_map_t
);
363 extern void *get_bsdthread_info(thread_act_t
);
364 extern void set_bsdthread_info(thread_act_t
, void *);
365 extern task_t
get_threadtask(thread_act_t
);
367 #endif /* __APPLE_API_PRIVATE */
369 #ifdef __APPLE_API_UNSTABLE
371 #if !defined(MACH_KERNEL_PRIVATE)
373 extern thread_act_t
current_act(void);
375 #endif /* MACH_KERNEL_PRIVATE */
377 #endif /* __APPLE_API_UNSTABLE */
379 extern kern_return_t
thread_abort(thread_act_t
);
380 extern kern_return_t
thread_abort_safely(thread_act_t
);
381 extern kern_return_t
thread_resume(thread_act_t
);
382 extern kern_return_t
thread_suspend(thread_act_t
);
383 extern kern_return_t
thread_terminate(thread_act_t
);
385 #endif /* _KERN_THREAD_ACT_H_ */