]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/thread_act.h
xnu-344.23.tar.gz
[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 * 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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * @OSF_FREE_COPYRIGHT@
24 */
25 /*
26 * Copyright (c) 1993 The University of Utah and
27 * the Computer Systems Laboratory (CSL). All rights reserved.
28 *
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.
34 *
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.
38 *
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.
41 *
42 * Author: Bryan Ford, University of Utah CSL
43 *
44 * File: thread_act.h
45 *
46 * thread activation definitions
47 */
48 #ifndef _KERN_THREAD_ACT_H_
49 #define _KERN_THREAD_ACT_H_
50
51 #include <mach/mach_types.h>
52 #include <mach/vm_param.h>
53 #include <mach/thread_info.h>
54 #include <mach/exception_types.h>
55
56 #include <sys/appleapiopts.h>
57
58 #ifdef __APPLE_API_PRIVATE
59
60 #ifdef MACH_KERNEL_PRIVATE
61
62 #include <mach_assert.h>
63 #include <thread_swapper.h>
64 #include <cputypes.h>
65
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>
73
74 /*
75 * Here is a description of the states an thread_activation may be in.
76 *
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.
80 *
81 * The thread holds a reference on the activation while using it.
82 *
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
88 * thread pointer.
89 *
90 * An activation is suspended when suspend_count > 0.
91 *
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().
100 */
101
102 typedef struct ReturnHandler {
103 struct ReturnHandler *next;
104 void (*handler)(struct ReturnHandler *rh,
105 struct thread_activation *thr_act);
106 } ReturnHandler;
107
108 typedef struct thread_activation {
109
110 /*** task linkage ***/
111
112 /* Links for task's circular list of activations. The activation
113 * is only on the task's activation list while active. Must be
114 * first.
115 */
116 queue_chain_t thr_acts;
117
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
121 * this information.
122 */
123 boolean_t kernel_loaded; /* running in kernel-loaded task */
124 boolean_t kernel_loading; /* about to run kernel-loaded */
125
126 boolean_t inited;
127
128 /*** Machine-dependent state ***/
129 struct MachineThrAct mact;
130
131 /*** Consistency ***/
132 decl_mutex_data(,lock)
133 decl_simple_lock_data(,sched_lock)
134 int ref_count;
135
136 /* Reference to the task this activation is in.
137 * Constant for the life of the activation
138 */
139 struct task *task;
140 vm_map_t map; /* cached current map */
141
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.
145 */
146 struct thread_shuttle *thread;
147
148 /* The rest in this section is only valid when thread is nonzero. */
149
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.
153 */
154 struct thread_activation *higher, *lower;
155
156 /* Alert bits pending at this activation; some of them may have
157 * propagated from lower activations.
158 */
159 unsigned alerts;
160
161 /* Mask of alert bits to be allowed to pass through from lower levels.
162 */
163 unsigned alert_mask;
164
165 /*** Control information ***/
166
167 /* Number of outstanding suspensions on this activation. */
168 int suspend_count;
169
170 /* User-visible scheduling state */
171 int user_stop_count; /* outstanding stops */
172
173 /* ast is needed - see ast.h */
174 ast_t ast;
175
176 /* This is normally true, but is set to false when the
177 * activation is terminated.
178 */
179 int active;
180
181 /* Chain of return handlers to be called before the thread is
182 * allowed to return to this invocation
183 */
184 ReturnHandler *handlers;
185
186 /* A special ReturnHandler attached to the above chain to
187 * handle suspension and such
188 */
189 ReturnHandler special_handler;
190
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];
195
196 /* A list of ulocks (a lock set element) currently held by the thread
197 */
198 queue_head_t held_ulocks;
199
200 #if MACH_PROF
201 /* Profiling data structures */
202 boolean_t act_profiled; /* is activation being profiled? */
203 boolean_t act_profiled_own;
204 /* is activation being profiled
205 * on its own ? */
206 struct prof_data *profil_buffer;/* prof struct if either is so */
207 #endif /* MACH_PROF */
208
209 #ifdef MACH_BSD
210 void *uthread;
211 #endif
212
213 } Thread_Activation;
214
215 /* Alert bits */
216 #define SERVER_TERMINATED 0x01
217 #define ORPHANED 0x02
218 #define CLIENT_TERMINATED 0x04
219 #define TIME_CONSTRAINT_UNSATISFIED 0x08
220
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)
225
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).
230 */
231 #define ACT_MAX_REFERENCES \
232 (unsigned)(~0 ^ (1 << (sizeof(int)*BYTE_SIZE - 1)))
233
234 #define act_reference_fast(thr_act) \
235 MACRO_BEGIN \
236 if (thr_act) { \
237 act_lock(thr_act); \
238 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
239 (thr_act)->ref_count++; \
240 act_unlock(thr_act); \
241 } \
242 MACRO_END
243
244 #define act_reference(thr_act) act_reference_fast(thr_act)
245
246 #define act_locked_act_reference(thr_act) \
247 MACRO_BEGIN \
248 if (thr_act) { \
249 assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
250 (thr_act)->ref_count++; \
251 } \
252 MACRO_END
253
254 #define act_deallocate_fast(thr_act) \
255 MACRO_BEGIN \
256 if (thr_act) { \
257 int new_value; \
258 act_lock(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) \
264 act_free(thr_act); \
265 } \
266 MACRO_END
267
268 #define act_deallocate(thr_act) act_deallocate_fast(thr_act)
269
270 #define act_locked_act_deallocate(thr_act) \
271 MACRO_BEGIN \
272 if (thr_act) { \
273 int new_value; \
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"); \
279 } \
280 } \
281 MACRO_END
282
283 extern struct thread_activation pageout_act;
284
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);
289
290 extern kern_return_t thread_get_special_port(thread_act_t, int,
291 ipc_port_t *);
292 extern kern_return_t thread_set_special_port(thread_act_t, int,
293 ipc_port_t);
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);
303
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);
317
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);
323
324 extern int dump_act(thread_act_t); /* debugging */
325
326 #if MACH_ASSERT
327 /*
328 * Debugging support - "watchacts", a patchable selective trigger
329 */
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 (!!) */
342 #define WA_ALL (~0)
343 #endif /* MACH_ASSERT */
344
345 #else /* MACH_KERNEL_PRIVATE */
346
347 extern void act_reference(thread_act_t);
348 extern void act_deallocate(thread_act_t);
349
350 #endif /* MACH_KERNEL_PRIVATE */
351
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);
355
356 typedef void (thread_apc_handler_t)(thread_act_t);
357
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);
360
361 extern vm_map_t swap_act_map(thread_act_t, vm_map_t);
362
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);
366
367 #endif /* __APPLE_API_PRIVATE */
368
369 #ifdef __APPLE_API_UNSTABLE
370
371 #if !defined(MACH_KERNEL_PRIVATE)
372
373 extern thread_act_t current_act(void);
374
375 #endif /* MACH_KERNEL_PRIVATE */
376
377 #endif /* __APPLE_API_UNSTABLE */
378
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);
384
385 #endif /* _KERN_THREAD_ACT_H_ */