]>
Commit | Line | Data |
---|---|---|
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_ */ |