]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
d7e50217 | 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 7 | * |
d7e50217 A |
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 | |
1c79356b A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
d7e50217 A |
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. | |
1c79356b A |
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> | |
1c79356b A |
55 | #include <mach/vm_param.h> |
56 | #include <mach/thread_info.h> | |
57 | #include <mach/exception_types.h> | |
58 | ||
9bccf70c A |
59 | #include <sys/appleapiopts.h> |
60 | ||
61 | #ifdef __APPLE_API_PRIVATE | |
62 | ||
63 | #ifdef MACH_KERNEL_PRIVATE | |
1c79356b | 64 | |
1c79356b A |
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> | |
1c79356b A |
74 | #include <ipc/ipc_port.h> |
75 | #include <machine/thread_act.h> | |
76 | ||
9bccf70c A |
77 | /* |
78 | * Here is a description of the states an thread_activation may be in. | |
1c79356b A |
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 | * | |
9bccf70c | 84 | * The thread holds a reference on the activation while using it. |
1c79356b A |
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 | |
9bccf70c A |
90 | * still on an RPC chain. A terminated activation always has a null |
91 | * thread pointer. | |
1c79356b A |
92 | * |
93 | * An activation is suspended when suspend_count > 0. | |
1c79356b A |
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() | |
9bccf70c | 98 | * be held, but migration through the activation must be frozen (so that the |
1c79356b A |
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 | ||
9bccf70c A |
129 | boolean_t inited; |
130 | ||
1c79356b A |
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 | ||
1c79356b A |
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 | ||
1c79356b A |
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 */ | |
9bccf70c | 177 | ast_t ast; |
1c79356b A |
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 | ||
1c79356b A |
218 | /* Alert bits */ |
219 | #define SERVER_TERMINATED 0x01 | |
220 | #define ORPHANED 0x02 | |
221 | #define CLIENT_TERMINATED 0x04 | |
222 | #define TIME_CONSTRAINT_UNSATISFIED 0x08 | |
223 | ||
1c79356b A |
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 | ||
1c79356b A |
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 | ||
9bccf70c | 286 | extern struct thread_activation pageout_act; |
1c79356b A |
287 | |
288 | extern void act_init(void); | |
1c79356b A |
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); | |
1c79356b | 292 | |
1c79356b A |
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 | ||
9bccf70c A |
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 */ | |
1c79356b | 347 | |
9bccf70c | 348 | #else /* MACH_KERNEL_PRIVATE */ |
1c79356b | 349 | |
1c79356b A |
350 | extern void act_reference(thread_act_t); |
351 | extern void act_deallocate(thread_act_t); | |
352 | ||
9bccf70c | 353 | #endif /* MACH_KERNEL_PRIVATE */ |
1c79356b | 354 | |
1c79356b A |
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 | ||
9bccf70c | 359 | typedef void (thread_apc_handler_t)(thread_act_t); |
1c79356b A |
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 | ||
9bccf70c | 364 | extern vm_map_t swap_act_map(thread_act_t, vm_map_t); |
1c79356b A |
365 | |
366 | extern void *get_bsdthread_info(thread_act_t); | |
367 | extern void set_bsdthread_info(thread_act_t, void *); | |
9bccf70c A |
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); | |
1c79356b A |
387 | |
388 | #endif /* _KERN_THREAD_ACT_H_ */ |