|
|
1.1 root 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 [email protected] 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/rpc.h>
53: #include <mach/vm_param.h>
54: #include <mach/thread_info.h>
55: #include <mach/exception_types.h>
56:
57:
58: #ifdef MACH_KERNEL_PRIVATE
59: #include <mach_assert.h>
60: #include <xkmachkernel.h>
61: #include <thread_swapper.h>
62: #include <cputypes.h>
63:
64: #include <kern/lock.h>
65: #include <kern/queue.h>
66: #include <kern/etap_macros.h>
67: #include <kern/thread.h>
68: #include <kern/thread_pool.h>
69: #include <ipc/ipc_port.h>
70: #include <machine/thread_act.h>
71:
72: /* Here is a description of the states an thread_activation may be in.
73: *
74: * An activation always has a valid task pointer, and it is always constant.
75: * The activation is only linked onto the task's activation list until
76: * the activation is terminated.
77: *
78: * An activation is in use or not, depending on whether its thread
79: * pointer is nonzero. If it is not in use, it is just sitting idly
80: * waiting to be used by a thread. The thread holds a reference on
81: * the activation while using it.
82: *
83: * An activation lives on an thread_pool if its pool_port pointer is nonzero.
84: * When in use, it can still live on an thread_pool, but it is not actually
85: * linked onto the thread_pool's list of available activations. In this case,
86: * the act will return to its thread_pool as soon as it becomes unused.
87: *
88: * An activation is active until thread_terminate is called on it;
89: * then it is inactive, waiting for all references to be dropped.
90: * Future control operations on the terminated activation will fail,
91: * with the exception that act_yank still works if the activation is
92: * still on an RPC chain. A terminated activation always has null
93: * thread and pool_port pointers.
94: *
95: * An activation is suspended when suspend_count > 0.
96: * A suspended activation can live on an thread_pool, but it is not
97: * actually linked onto the thread_pool while suspended.
98: *
99: * Locking note: access to data relevant to scheduling state (user_stop_count,
100: * suspend_count, handlers, special_handler) is controlled by the combination
101: * of locks acquired by act_lock_thread(). That is, not only must act_lock()
102: * be held, but RPC through the activation must be frozen (so that the
103: * thread pointer doesn't change). If a shuttle is associated with the
104: * activation, then its thread_lock() must also be acquired to change these
105: * data. Regardless of whether a shuttle is present, the data must be
106: * altered at splsched().
107: */
108:
109: typedef struct ReturnHandler {
110: struct ReturnHandler *next;
111: void (*handler)(struct ReturnHandler *rh,
112: struct thread_activation *thr_act);
113: } ReturnHandler;
114:
115: typedef struct thread_activation {
116:
117: /*** task linkage ***/
118:
119: /* Links for task's circular list of activations. The activation
120: * is only on the task's activation list while active. Must be
121: * first.
122: */
123: queue_chain_t thr_acts;
124:
125: /* Indicators for whether this activation is in the midst of
126: * resuming or has already been resumed in a kernel-loaded
127: * task -- these flags are basically for quick access to
128: * this information.
129: */
130: boolean_t kernel_loaded; /* running in kernel-loaded task */
131: boolean_t kernel_loading; /* about to run kernel-loaded */
132:
133: /*** Machine-dependent state ***/
134: struct MachineThrAct mact;
135:
136: /*** Consistency ***/
137: decl_mutex_data(,lock)
138: decl_simple_lock_data(,sched_lock)
139: int ref_count;
140:
141: /* Reference to the task this activation is in.
142: * Constant for the life of the activation
143: */
144: struct task *task;
145: vm_map_t map; /* cached current map */
146:
147: /*** thread_pool-related stuff ***/
148: /* Port containing the thread_pool this activation normally lives
149: * on, zero if none. The port (really the thread_pool) holds a
150: * reference to the activation as long as this is nonzero (even when
151: * the activation isn't actually on the thread_pool's list).
152: */
153: struct ipc_port *pool_port;
154:
155: /* Link on the thread_pool's list of activations.
156: * The activation is only actually on the thread_pool's list
157: * (and hence this is valid) when not in use (thread == 0) and
158: * not suspended (suspend_count == 0).
159: */
160: struct thread_activation *thread_pool_next;
161:
162: /* User stack location and size for initialization on migrating RPCs */
163: vm_offset_t user_stack;
164: vm_size_t user_stack_size;
165:
166: /*
167: * Entry point for upcall w/o registered subsystem and pointer
168: * to return code
169: */
170: entry_function_t user_entry;
171:
172: /* RPC state */
173: union {
174: struct {
175: rpc_subsystem_t r_subsystem;
176: #if 0 /* Grenoble */
177: mach_rpc_id_t r_routine_num;
178: mach_rpc_signature_t r_sig_ptr;
179: mach_rpc_size_t r_sig_size;
180: #else
181: rpc_id_t r_routine_num;
182: rpc_signature_t r_sig_ptr; /* Stored Client Sig Ptr */
183: rpc_size_t r_sig_size; /* Size of Sig stored */
184: struct rpc_signature r_sigbuf; /* Static Reservation of Sig Mem */
185: routine_descriptor_t r_sigbufp; /* For dynamic storage of Sig */
186: vm_size_t r_sigbuf_size; /* Size of buffer allocated for sig */
187: #endif
188: vm_offset_t r_new_argv;
189: vm_offset_t *r_arg_buf;
190: vm_offset_t r_arg_buf_data[RPC_KBUF_SIZE];
191: rpc_copy_state_t r_state;
192: rpc_copy_state_data_t r_state_data[RPC_DESC_COUNT];
193: unsigned int r_port_flags;
194: ipc_port_t r_local_port;
195: void *r_kkt_args;
196: } regular;
197: struct {
198: ipc_port_t r_port;
199: ipc_port_t r_exc_port;
200: int r_exc_flavor;
201: mach_msg_type_number_t r_ostate_cnt;
202: exception_data_type_t r_code[EXCEPTION_CODE_MAX];
203: #if ETAP_EVENT_MONITOR
204: exception_type_t r_exception;
205: #endif
206: } exception;
207: } rpc_state;
208:
209: /*** Thread linkage ***/
210: /* Shuttle using this activation, zero if not in use. The shuttle
211: * holds a reference on the activation while this is nonzero.
212: */
213: struct thread_shuttle *thread;
214:
215: /* The rest in this section is only valid when thread is nonzero. */
216:
217: /* Next higher and next lower activation on the thread's activation
218: * stack. For a topmost activation or the null_act, higher is
219: * undefined. The bottommost activation is always the null_act.
220: */
221: struct thread_activation *higher, *lower;
222:
223: /* Alert bits pending at this activation; some of them may have
224: * propagated from lower activations.
225: */
226: unsigned alerts;
227:
228: /* Mask of alert bits to be allowed to pass through from lower levels.
229: */
230: unsigned alert_mask;
231:
232: #if 0 /* Grenoble */
233: /* Saved policy and priority of shuttle if changed to migrate into
234: * higher-priority or more real-time task. Only valid if
235: * saved_sched_stamp is nonzero and equal to the sched_change_stamp
236: * in the thread_shuttle. (Otherwise, the policy or priority has
237: * been explicitly changed in the meantime, and the saved values
238: * are invalid.)
239: */
240: policy_t saved_policy;
241: integer_t saved_base_priority;
242: unsigned int saved_sched_change_stamp;
243: #endif
244: /*** Control information ***/
245:
246: /* Number of outstanding suspensions on this activation. */
247: int suspend_count;
248:
249: /* User-visible scheduling state */
250: int user_stop_count; /* outstanding stops */
251:
252: /* ast is needed - see ast.h */
253: int ast;
254:
255: #if THREAD_SWAPPER
256: /* task swapper */
257: int swap_state; /* swap state (or unswappable flag)*/
258: queue_chain_t swap_queue; /* links on swap queues */
259: #if MACH_ASSERT
260: boolean_t kernel_stack_swapped_in;
261: /* debug for thread swapping */
262: #if THREAD_SWAP_UNWIRE_USER_STACK
263: boolean_t user_stack_swapped_in;
264: /* debug for thread swapping */
265: #endif /* THREAD_SWAP_UNWIRE_USER_STACK */
266: #endif /* MACH_ASSERT */
267: #endif /* THREAD_SWAPPER */
268:
269: /* This is normally true, but is set to false when the
270: * activation is terminated.
271: */
272: int active;
273:
274: /* Chain of return handlers to be called before the thread is
275: * allowed to return to this invocation
276: */
277: ReturnHandler *handlers;
278:
279: /* A special ReturnHandler attached to the above chain to
280: * handle suspension and such
281: */
282: ReturnHandler special_handler;
283:
284: /* Special ports attached to this activation */
285: struct ipc_port *ith_self; /* not a right, doesn't hold ref */
286: struct ipc_port *ith_sself; /* a send right */
287: struct exception_action exc_actions[EXC_TYPES_COUNT];
288:
289: /* A list of ulocks (a lock set element) currently held by the thread
290: */
291: queue_head_t held_ulocks;
292:
293: #if XKMACHKERNEL
294: void *xk_resources;
295: #endif /* XKMACHKERNEL */
296:
297: #if MACH_PROF
298: /* Profiling data structures */
299: boolean_t act_profiled; /* is activation being profiled? */
300: boolean_t act_profiled_own;
301: /* is activation being profiled
302: * on its own ? */
303: struct prof_data *profil_buffer;/* prof struct if either is so */
304: #endif /* MACH_PROF */
305: #ifdef MACH_BSD
306: /*
307: * WARNING: you must change this constant if the size of
308: * user.h:struct uthread changes
309: */
310: unsigned char bsd_space[288];
311: #endif
312:
313: } Thread_Activation;
314:
315: /* RPC state fields */
316: #define r_subsystem rpc_state.regular.r_subsystem
317: #define r_routine_num rpc_state.regular.r_routine_num
318: #define r_sig_ptr rpc_state.regular.r_sig_ptr
319: #define r_sig_size rpc_state.regular.r_sig_size
320: #define r_sigbuf rpc_state.regular.r_sigbuf
321: #define r_sigbufp rpc_state.regular.r_sigbufp
322: #define r_sigbuf_size rpc_state.regular.r_sigbuf_size
323: #define r_new_argv rpc_state.regular.r_new_argv
324: #define r_arg_buf rpc_state.regular.r_arg_buf
325: #define r_arg_buf_data rpc_state.regular.r_arg_buf_data
326: #define r_state rpc_state.regular.r_state
327: #define r_state_data rpc_state.regular.r_state_data
328: #define r_port_flags rpc_state.regular.r_port_flags
329: #define r_local_port rpc_state.regular.r_local_port
330: #define r_kkt_args rpc_state.regular.r_kkt_args
331: #define r_port rpc_state.exception.r_port
332: #define r_exc_port rpc_state.exception.r_exc_port
333: #define r_exc_flavor rpc_state.exception.r_exc_flavor
334: #define r_ostate_cnt rpc_state.exception.r_ostate_cnt
335: #define r_code rpc_state.exception.r_code
336: #define r_exception rpc_state.exception.r_exception
337:
338: /* Alert bits */
339: #define SERVER_TERMINATED 0x01
340: #define ORPHANED 0x02
341: #define CLIENT_TERMINATED 0x04
342: #define TIME_CONSTRAINT_UNSATISFIED 0x08
343:
344: #if THREAD_SWAPPER
345: /*
346: * Encapsulate the actions needed to ensure that next lower act on
347: * RPC chain is swapped in. Used at base spl; assumes rpc_lock()
348: * of thread is held; if port is non-null, assumes its ip_lock()
349: * is also held.
350: */
351: #define act_switch_swapcheck(thread, port) \
352: MACRO_BEGIN \
353: thread_act_t __act__ = thread->top_act; \
354: \
355: while (__act__->lower) { \
356: thread_act_t __l__ = __act__->lower; \
357: \
358: if (__l__->swap_state == TH_SW_IN || \
359: __l__->swap_state == TH_SW_UNSWAPPABLE) \
360: break; \
361: /* \
362: * XXX - Do we need to reference __l__? \
363: */ \
364: if (port) \
365: ip_unlock(port); \
366: if (!thread_swapin_blocking(__l__)) \
367: panic("act_switch_swapcheck: !active"); \
368: if (port) \
369: ip_lock(port); \
370: if (__act__->lower == __l__) \
371: break; \
372: } \
373: MACRO_END
374:
375: #else /* !THREAD_SWAPPER */
376:
377: #define act_switch_swapcheck(thread, port)
378:
379: #endif /* !THREAD_SWAPPER */
380:
381: #define act_lock_init(thr_act) mutex_init(&(thr_act)->lock, ETAP_THREAD_ACT)
382: #define act_lock(thr_act) mutex_lock(&(thr_act)->lock)
383: #define act_lock_try(thr_act) mutex_try(&(thr_act)->lock)
384: #define act_unlock(thr_act) mutex_unlock(&(thr_act)->lock)
385:
386: /* Sanity check the ref count. If it is 0, we may be doubly zfreeing.
387: * If it is larger than max int, it has been corrupted, probably by being
388: * modified into an address (this is architecture dependent, but it's
389: * safe to assume there cannot really be max int references).
390: */
391: #define ACT_MAX_REFERENCES \
392: (unsigned)(~0 ^ (1 << (sizeof(int)*BYTE_SIZE - 1)))
393:
394: #define act_reference(thr_act) \
395: MACRO_BEGIN \
396: if (thr_act) { \
397: act_lock(thr_act); \
398: assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
399: if ((thr_act)->ref_count <= 0) \
400: panic("act_reference: already freed"); \
401: (thr_act)->ref_count++; \
402: act_unlock(thr_act); \
403: } \
404: MACRO_END
405:
406: #define act_locked_act_reference(thr_act) \
407: MACRO_BEGIN \
408: if (thr_act) { \
409: assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
410: if ((thr_act)->ref_count <= 0) \
411: panic("a_l_act_reference: already freed"); \
412: (thr_act)->ref_count++; \
413: } \
414: MACRO_END
415:
416: #define sigbuf_dealloc(thr_act) \
417: if ((thr_act->r_sigbufp) && (thr_act->r_sigbuf_size > \
418: sizeof(thr_act->r_sigbuf))) \
419: { \
420: KFREE((vm_offset_t)thr_act->r_sigbufp, \
421: thr_act->r_sigbuf_size, \
422: thr_act->r_port_flags & IPC_PORT_FLAGS_RT); \
423: thr_act->r_sigbuf_size = 0; \
424: }
425:
426: #define act_deallocate(thr_act) \
427: MACRO_BEGIN \
428: if (thr_act) { \
429: int new_value; \
430: act_lock(thr_act); \
431: assert((thr_act)->ref_count > 0 && \
432: (thr_act)->ref_count <= ACT_MAX_REFERENCES); \
433: new_value = --(thr_act)->ref_count; \
434: if (new_value == 0) { \
435: sigbuf_dealloc(thr_act); \
436: act_free(thr_act); \
437: } \
438: else act_unlock(thr_act); \
439: } \
440: MACRO_END
441:
442: #define act_locked_act_deallocate(thr_act) \
443: MACRO_BEGIN \
444: if (thr_act) { \
445: int new_value; \
446: assert((thr_act)->ref_count > 0 && \
447: (thr_act)->ref_count <= ACT_MAX_REFERENCES); \
448: new_value = --(thr_act)->ref_count; \
449: if (new_value == 0) { \
450: panic("a_l_act_deallocate: would free act"); \
451: } \
452: } \
453: MACRO_END
454:
455:
456: extern void act_init(void);
457: extern kern_return_t act_disable_task_locked(thread_act_t);
458: extern void thread_release(thread_act_t);
459: extern kern_return_t thread_dowait(thread_act_t, boolean_t);
460: extern void thread_hold(thread_act_t);
461: extern void nudge(thread_act_t);
462:
463: extern kern_return_t act_set_thread_pool(thread_act_t, ipc_port_t);
464: extern kern_return_t act_locked_act_set_thread_pool(thread_act_t, ipc_port_t);
465: extern kern_return_t thread_get_special_port(thread_act_t, int,
466: ipc_port_t *);
467: extern kern_return_t thread_set_special_port(thread_act_t, int,
468: ipc_port_t);
469: extern thread_t act_lock_thread(thread_act_t);
470: extern void act_unlock_thread(thread_act_t);
471: extern void install_special_handler(thread_act_t);
472: extern thread_act_t thread_lock_act(thread_t);
473: extern void thread_unlock_act(thread_t);
474: extern void act_attach(thread_act_t, thread_t, unsigned);
475: extern void act_execute_returnhandlers(void);
476: extern void act_detach(thread_act_t);
477: extern void act_free(thread_act_t);
478:
479: /* machine-dependent functions */
480: extern void act_machine_return(kern_return_t);
481: extern void act_machine_init(void);
482: extern kern_return_t act_machine_create(struct task *, thread_act_t);
483: extern void act_machine_destroy(thread_act_t);
484: extern kern_return_t act_machine_set_state(thread_act_t,
485: thread_flavor_t, thread_state_t,
486: mach_msg_type_number_t );
487: extern kern_return_t act_machine_get_state(thread_act_t,
488: thread_flavor_t, thread_state_t,
489: mach_msg_type_number_t *);
490: extern void act_machine_switch_pcb(thread_act_t);
491:
492: extern kern_return_t act_create(task_t, thread_act_params_t params,
493: thread_act_t *);
494: extern kern_return_t act_get_state(thread_act_t, int, thread_state_t,
495: mach_msg_type_number_t *);
496: extern kern_return_t act_set_state(thread_act_t, int, thread_state_t,
497: mach_msg_type_number_t);
498:
499: extern int dump_act(thread_act_t); /* debugging */
500:
501: #define current_act_fast() (current_thread()->top_act)
502: #define current_act_slow() ((current_thread()) ? \
503: current_act_fast() : \
504: THR_ACT_NULL)
505:
506: #define current_act() current_act_slow() /* JMM - til we find the culprit */
507:
508: #else /* !MACH_KERNEL_PRIVATE */
509:
510: extern thread_act_t current_act(void);
511:
512: #endif /* !MACH_KERNEL_PRIVATE */
513:
514: /* Exported to world */
515: extern kern_return_t act_alert(thread_act_t, unsigned);
516: extern kern_return_t act_alert_mask(thread_act_t, unsigned );
517: extern kern_return_t post_alert(thread_act_t, unsigned);
518:
519: extern kern_return_t thread_abort(thread_act_t);
520: extern kern_return_t thread_abort_safely(thread_act_t);
521: extern kern_return_t thread_resume(thread_act_t);
522: extern kern_return_t thread_suspend(thread_act_t);
523: extern kern_return_t thread_terminate(thread_act_t);
524:
525: typedef void (thread_apc_handler_t)(thread_act_t);
526:
527: extern kern_return_t thread_apc_set(thread_act_t, thread_apc_handler_t);
528: extern kern_return_t thread_apc_clear(thread_act_t, thread_apc_handler_t);
529:
530: extern void set_act_map(thread_act_t, vm_map_t);
531:
532: extern void *get_bsdthread_info(thread_act_t);
533: extern void set_bsdthread_info(thread_act_t, void *);
534: extern task_t get_threadtask(thread_act_t);
535:
536: #endif /* _KERN_THREAD_ACT_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.