]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/thread_act.h
4e7e1d58c4325696ab0afb16fc44c19d93f70436
[apple/xnu.git] / osfmk / kern / thread_act.h
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
13 * file.
14 *
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * @OSF_FREE_COPYRIGHT@
27 */
28 /*
29 * Copyright (c) 1993 The University of Utah and
30 * the Computer Systems Laboratory (CSL). All rights reserved.
31 *
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.
37 *
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.
41 *
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.
44 *
45 * Author: Bryan Ford, University of Utah CSL
46 *
47 * File: thread_act.h
48 *
49 * thread activation definitions
50 */
51 #ifndef _KERN_THREAD_ACT_H_
52 #define _KERN_THREAD_ACT_H_
53
54 #include <mach/mach_types.h>
55 #include <mach/vm_param.h>
56 #include <mach/thread_info.h>
57 #include <mach/exception_types.h>
58
59 #include <sys/appleapiopts.h>
60
61 #ifdef __APPLE_API_PRIVATE
62
63 #ifdef MACH_KERNEL_PRIVATE
64
65 #include <mach_assert.h>
66 #include <thread_swapper.h>
67 #include <cputypes.h>
68
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>
76
77 /*
78 * Here is a description of the states an thread_activation may be in.
79 *
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.
83 *
84 * The thread holds a reference on the activation while using it.
85 *
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
91 * thread pointer.
92 *
93 * An activation is suspended when suspend_count > 0.
94 *
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().
103 */
104
105 typedef struct ReturnHandler {
106 struct ReturnHandler *next;
107 void (*handler)(struct ReturnHandler *rh,
108 struct thread_activation *thr_act);
109 } ReturnHandler;
110
111 typedef struct thread_activation {
112
113 /*** task linkage ***/
114
115 /* Links for task's circular list of activations. The activation
116 * is only on the task's activation list while active. Must be
117 * first.
118 */
119 queue_chain_t thr_acts;
120
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
124 * this information.
125 */
126 boolean_t kernel_loaded; /* running in kernel-loaded task */
127 boolean_t kernel_loading; /* about to run kernel-loaded */
128
129 boolean_t inited;
130
131 /*** Machine-dependent state ***/
132 struct MachineThrAct mact;
133
134 /*** Consistency ***/
135 decl_mutex_data(,lock)
136 decl_simple_lock_data(,sched_lock)
137 int ref_count;
138
139 /* Reference to the task this activation is in.
140 * Constant for the life of the activation
141 */
142 struct task *task;
143 vm_map_t map; /* cached current map */
144
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.
148 */
149 struct thread_shuttle *thread;
150
151 /* The rest in this section is only valid when thread is nonzero. */
152
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.
156 */
157 struct thread_activation *higher, *lower;
158
159 /* Alert bits pending at this activation; some of them may have
160 * propagated from lower activations.
161 */
162 unsigned alerts;
163
164 /* Mask of alert bits to be allowed to pass through from lower levels.
165 */
166 unsigned alert_mask;
167
168 /*** Control information ***/
169
170 /* Number of outstanding suspensions on this activation. */
171 int suspend_count;
172
173 /* User-visible scheduling state */
174 int user_stop_count; /* outstanding stops */
175
176 /* ast is needed - see ast.h */
177 ast_t ast;
178
179 /* This is normally true, but is set to false when the
180 * activation is terminated.
181 */
182 int active;
183
184 /* Chain of return handlers to be called before the thread is
185 * allowed to return to this invocation
186 */
187 ReturnHandler *handlers;
188
189 /* A special ReturnHandler attached to the above chain to
190 * handle suspension and such
191 */
192 ReturnHandler special_handler;
193
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];
198
199 /* A list of ulocks (a lock set element) currently held by the thread
200 */
201 queue_head_t held_ulocks;
202
203 #if MACH_PROF
204 /* Profiling data structures */
205 boolean_t act_profiled; /* is activation being profiled? */
206 boolean_t act_profiled_own;
207 /* is activation being profiled
208 * on its own ? */
209 struct prof_data *profil_buffer;/* prof struct if either is so */
210 #endif /* MACH_PROF */
211
212 #ifdef MACH_BSD
213 void *uthread;
214 #endif
215
216 } Thread_Activation;
217
218 /* Alert bits */
219 #define SERVER_TERMINATED 0x01
220 #define ORPHANED 0x02
221 #define CLIENT_TERMINATED 0x04
222 #define TIME_CONSTRAINT_UNSATISFIED 0x08
223
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)
228
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).
233 */
234 #define ACT_MAX_REFERENCES \
235 (unsigned)(~0 ^ (1 << (sizeof(int)*BYTE_SIZE - 1)))
236
237 #define act_reference_fast(thr_act) \
238 MACRO_BEGIN \
239 if (thr_act) { \
240 act_lock(thr_act); \
241 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
242 (thr_act)->ref_count++; \
243 act_unlock(thr_act); \
244 } \
245 MACRO_END
246
247 #define act_reference(thr_act) act_reference_fast(thr_act)
248
249 #define act_locked_act_reference(thr_act) \
250 MACRO_BEGIN \
251 if (thr_act) { \
252 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
253 (thr_act)->ref_count++; \
254 } \
255 MACRO_END
256
257 #define act_deallocate_fast(thr_act) \
258 MACRO_BEGIN \
259 if (thr_act) { \
260 int new_value; \
261 act_lock(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) \
267 act_free(thr_act); \
268 } \
269 MACRO_END
270
271 #define act_deallocate(thr_act) act_deallocate_fast(thr_act)
272
273 #define act_locked_act_deallocate(thr_act) \
274 MACRO_BEGIN \
275 if (thr_act) { \
276 int new_value; \
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"); \
282 } \
283 } \
284 MACRO_END
285
286 extern struct thread_activation pageout_act;
287
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);
292
293 extern kern_return_t thread_get_special_port(thread_act_t, int,
294 ipc_port_t *);
295 extern kern_return_t thread_set_special_port(thread_act_t, int,
296 ipc_port_t);
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);
306
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);
320
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);
326
327 extern int dump_act(thread_act_t); /* debugging */
328
329 #if MACH_ASSERT
330 /*
331 * Debugging support - "watchacts", a patchable selective trigger
332 */
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 (!!) */
345 #define WA_ALL (~0)
346 #endif /* MACH_ASSERT */
347
348 #else /* MACH_KERNEL_PRIVATE */
349
350 extern void act_reference(thread_act_t);
351 extern void act_deallocate(thread_act_t);
352
353 #endif /* MACH_KERNEL_PRIVATE */
354
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);
358
359 typedef void (thread_apc_handler_t)(thread_act_t);
360
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);
363
364 extern vm_map_t swap_act_map(thread_act_t, vm_map_t);
365
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);
369
370 #endif /* __APPLE_API_PRIVATE */
371
372 #ifdef __APPLE_API_UNSTABLE
373
374 #if !defined(MACH_KERNEL_PRIVATE)
375
376 extern thread_act_t current_act(void);
377
378 #endif /* MACH_KERNEL_PRIVATE */
379
380 #endif /* __APPLE_API_UNSTABLE */
381
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);
387
388 #endif /* _KERN_THREAD_ACT_H_ */