|
|
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: * Mach Operating System
27: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: */
52: /*
53: * File: thread.h
54: * Author: Avadis Tevanian, Jr.
55: *
56: * This file contains the structure definitions for threads.
57: *
58: */
59: /*
60: * Copyright (c) 1993 The University of Utah and
61: * the Computer Systems Laboratory (CSL). All rights reserved.
62: *
63: * Permission to use, copy, modify and distribute this software and its
64: * documentation is hereby granted, provided that both the copyright
65: * notice and this permission notice appear in all copies of the
66: * software, derivative works or modified versions, and any portions
67: * thereof, and that both notices appear in supporting documentation.
68: *
69: * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
70: * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
71: * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
72: *
73: * CSL requests users of this software to return to [email protected] any
74: * improvements that they make and grant CSL redistribution rights.
75: *
76: */
77:
78: #ifndef _KERN_THREAD_H_
79: #define _KERN_THREAD_H_
80:
81: #include <mach/kern_return.h>
82: #include <mach/mach_types.h>
83: #include <mach/message.h>
84: #include <mach/boolean.h>
85: #include <mach/vm_types.h>
86: #include <mach/vm_prot.h>
87: #include <mach/thread_info.h>
88: #include <mach/thread_status.h>
89: #include <kern/cpu_data.h> /* for current_thread */
90: #include <kern/kern_types.h>
91:
92: /*
93: * Logically, a thread of control consists of two parts:
94: * a thread_shuttle, which may migrate during an RPC, and
95: * a thread_activation, which remains attached to a task.
96: * The thread_shuttle is the larger portion of the two-part thread,
97: * and contains scheduling info, messaging support, accounting info,
98: * and links to the thread_activation within which the shuttle is
99: * currently operating.
100: *
101: * It might make sense to have the thread_shuttle be a proper sub-structure
102: * of the thread, with the thread containing links to both the shuttle and
103: * activation. In order to reduce the scope and complexity of source
104: * changes and the overhead of maintaining these linkages, we have subsumed
105: * the shuttle into the thread, calling it a thread_shuttle.
106: *
107: * User accesses to threads always come in via the user's thread port,
108: * which gets translated to a pointer to the target thread_activation.
109: * Kernel accesses intended to effect the entire thread, typically use
110: * a pointer to the thread_shuttle (current_thread()) as the target of
111: * their operations. This makes sense given that we have subsumed the
112: * shuttle into the thread_shuttle, eliminating one set of linkages.
113: * Operations effecting only the shuttle may use a thread_shuttle_t
114: * to indicate this.
115: *
116: * The current_act() macro returns a pointer to the current thread_act, while
117: * the current_thread() macro returns a pointer to the currently active
118: * thread_shuttle (representing the thread in its entirety).
119: */
120:
121: /*
122: * Possible results of thread_block - returned in
123: * current_thread()->wait_result.
124: */
125: #define THREAD_AWAKENED 0 /* normal wakeup */
126: #define THREAD_TIMED_OUT 1 /* timeout expired */
127: #define THREAD_INTERRUPTED 2 /* interrupted by clear_wait */
128: #define THREAD_RESTART 3 /* restart operation entirely */
129:
130: /*
131: * Interruptible flags for assert_wait
132: *
133: */
134: #define THREAD_UNINT 0 /* not interruptible */
135: #define THREAD_INTERRUPTIBLE 1 /* may not be restartable */
136: #define THREAD_ABORTSAFE 2 /* abortable safely */
137:
138: #ifdef MACH_KERNEL_PRIVATE
139: #include <cpus.h>
140: #include <hw_footprint.h>
141: #include <mach_host.h>
142: #include <mach_prof.h>
143: #include <dipc.h>
144: #include <xkmachkernel.h>
145: #include <mach_lock_mon.h>
146: #include <mach_ldebug.h>
147:
148: #include <mach/port.h>
149: #include <kern/ast.h>
150: #include <kern/cpu_number.h>
151: #include <kern/queue.h>
152: #include <kern/time_out.h>
153: #include <kern/timer.h>
154: #include <kern/lock.h>
155: #include <kern/sched.h>
156: #include <kern/sched_prim.h>
157: #include <kern/thread_pool.h>
158: #include <kern/thread_call.h>
159: #include <kern/thread_call_private.h>
160: #include <kern/task.h>
161: #include <ipc/ipc_kmsg.h>
162: #include <machine/thread.h>
163:
164:
165: typedef struct thread_shuttle {
166: /*
167: * Beginning of thread_shuttle proper. When the thread is on
168: * a wait queue, these three fields are in treated as an un-
169: * official union with a wait_queue_element. If you change
170: * these, you must change that definition as well.
171: */
172: queue_chain_t links; /* current run/wait queue links */
173: run_queue_t runq; /* run queue p is on SEE BELOW */
174: int whichq; /* which queue level p is on */
175:
176: /*
177: * NOTE: The runq field in the thread structure has an unusual
178: * locking protocol. If its value is RUN_QUEUE_NULL, then it is
179: * locked by the thread_lock, but if its value is something else
180: * (i.e. a run_queue) then it is locked by that run_queue's lock.
181: */
182:
183: /* Thread bookkeeping */
184: queue_chain_t pset_threads; /* list of all shuttles in proc set */
185:
186: /* Self-preservation */
187: decl_simple_lock_data(,lock) /* scheduling lock (thread_lock()) */
188: decl_simple_lock_data(,wake_lock) /* covers wake_active (wake_lock())*/
189: decl_mutex_data(,rpc_lock) /* RPC lock (rpc_lock()) */
190: int ref_count; /* number of references to me */
191:
192: vm_offset_t kernel_stack; /* accurate only if the thread is
193: not swapped and not executing */
194:
195: vm_offset_t stack_privilege;/* reserved kernel stack */
196:
197: /* Blocking information */
198: int reason; /* why we blocked */
199: event_t wait_event; /* event we are waiting on */
200: kern_return_t wait_result; /* outcome of wait -
201: may be examined by this thread
202: WITHOUT locking */
203: wait_queue_t wait_queue; /* wait queue we are currently on */
204: queue_chain_t wait_link; /* event's wait queue link */
205: boolean_t wake_active; /* Someone is waiting for this
206: thread to become suspended */
207: int state; /* Thread state: */
208: boolean_t preempt; /* Thread is undergoing preemption */
209:
210: #if ETAP_EVENT_MONITOR
211: int etap_reason; /* real reason why we blocked */
212: boolean_t etap_trace; /* ETAP trace status */
213: #endif /* ETAP_EVENT_MONITOR */
214:
215: /*
216: * Thread states [bits or'ed]
217: */
218: #define TH_WAIT 0x01 /* thread is queued for waiting */
219: #define TH_SUSP 0x02 /* thread has been asked to stop */
220: #define TH_RUN 0x04 /* thread is running or on runq */
221: #define TH_UNINT 0x08 /* thread is waiting uninteruptibly */
222: #define TH_HALTED 0x10 /* thread is halted at clean point ? */
223:
224: #define TH_ABORT 0x20 /* abort interruptible waits */
225: #define TH_SWAPPED_OUT 0x40 /* thread is swapped out */
226:
227: #define TH_IDLE 0x80 /* thread is an idle thread */
228:
229: #define TH_SCHED_STATE (TH_WAIT|TH_SUSP|TH_RUN|TH_UNINT)
230:
231: #define TH_STACK_HANDOFF 0x0100 /* thread has no kernel stack */
232: #define TH_STACK_COMING_IN 0x0200 /* thread is waiting for kernel stack */
233: #define TH_STACK_STATE (TH_STACK_HANDOFF | TH_STACK_COMING_IN)
234:
235: #define TH_TERMINATE 0x400 /* thread is terminating */
236:
237: #if 0 /* Grenoble version */
238: int preempt; /* Thread preemption status */
239: #define TH_PREEMPTABLE 0 /* Thread is preemptable */
240: #define TH_NOT_PREEMPTABLE 1 /* Thread is not preemptable */
241: #define TH_PREEMPTED 2 /* Thread has been preempted */
242:
243: #if ETAP_EVENT_MONITOR
244: int etap_reason; /* real reason why we blocked */
245: boolean_t etap_trace; /* ETAP trace status */
246: #endif /* ETAP_EVENT_MONITOR */
247:
248: #endif
249:
250: /* Stack handoff information */
251: void (*continuation)(/* start here next time runnable */
252: void);
253: int cont_arg; /* continuation argument */
254:
255: /* Scheduling information */
256: int policy; /* scheduling policy */
257: sp_info_t sp_info; /* policy-specific information */
258: int pending_policy; /* pending scheduling policy */
259: sp_attributes_t pending_sched_attr;
260: /* policy-specific information */
261: kern_return_t change_sfr; /* return value for pending change */
262: int sched_pri; /* scheduled (computed) priority */
263: unsigned int sleep_stamp; /* last time in TH_WAIT state */
264: #if 0 /* Grenoble */
265: unsigned int sched_change_stamp;
266: /* last time priority or policy was
267: explicitly changed (not the same
268: units as sched_stamp!) */
269: int unconsumed_quantum; /* leftover quantum (RR/FIFO) */
270: #endif
271:
272: /* VM global variables */
273: boolean_t vm_privilege; /* can use reserved memory? */
274: vm_offset_t recover; /* page fault recovery (copyin/out) */
275:
276: /* IPC data structures */
277:
278: struct ipc_kmsg_queue ith_messages;
279:
280: mach_port_t ith_mig_reply; /* reply port for mig */
281: mach_port_t ith_rpc_reply; /* reply port for kernel RPCs */
282:
283: /* Various bits of stashed state */
284: union {
285: struct {
286: mach_msg_return_t state; /* receive state */
287: mach_msg_size_t msize; /* max size for recvd msg */
288: struct ipc_kmsg *kmsg; /* received message */
289: mach_port_seqno_t seqno; /* seqno of recvd message */
290: mach_msg_option_t option;
291: mach_msg_body_t *scatter_list;
292: mach_msg_size_t scatter_list_size;
293: } receive;
294: char *other; /* catch-all for other state */
295: } saved;
296:
297: /* Timing data structures */
298: timer_data_t user_timer; /* user mode timer */
299: timer_data_t system_timer; /* system mode timer */
300: timer_data_t depressed_timer;/* depressed priority timer */
301: timer_save_data_t user_timer_save; /* saved user timer value */
302: timer_save_data_t system_timer_save; /* saved sys timer val. */
303: /*** ??? should the next two fields be moved to SP-specific struct?***/
304: unsigned int cpu_delta; /* cpu usage since last update */
305: unsigned int sched_delta; /* weighted cpu usage since update */
306:
307: /* Timers for time-outs */
308: thread_call_data_t wait_timer;
309: boolean_t wait_timer_is_set;
310: thread_call_data_t depress_timer;
311:
312: /* Ast/Halt data structures */
313: boolean_t active; /* how alive is the thread */
314:
315: /* Processor data structures */
316: processor_set_t processor_set; /* assigned processor set */
317: #if NCPUS > 1
318: processor_t bound_processor; /* bound to processor ?*/
319: #endif /* NCPUS > 1 */
320: #if MACH_HOST
321: boolean_t may_assign; /* may assignment change? */
322: boolean_t assign_active; /* someone waiting for may_assign */
323: #endif /* MACH_HOST */
324:
325: #if XKMACHKERNEL
326: int xk_type;
327: #endif /* XKMACHKERNEL */
328:
329: #if NCPUS > 1
330: processor_t last_processor; /* processor this last ran on */
331: #if MACH_LOCK_MON
332: unsigned lock_stack; /* number of locks held */
333: #endif /* MACH_LOCK_MON */
334: #endif /* NCPUS > 1 */
335:
336: int at_safe_point; /* thread_abort_safely allowed */
337: int funnel_state;
338: #define TH_FN_OWNED 0x1 /* we own the funnel lock */
339: #define TH_FN_REFUNNEL 0x2 /* must reaquire funnel lock when unblocking */
340:
341: #if MACH_LDEBUG
342: /*
343: * Debugging: track acquired mutexes and locks.
344: * Because a thread can block while holding such
345: * synchronizers, we think of the thread as
346: * "owning" them.
347: */
348: #define MUTEX_STACK_DEPTH 20
349: #define LOCK_STACK_DEPTH 20
350: mutex_t *mutex_stack[MUTEX_STACK_DEPTH];
351: lock_t *lock_stack[LOCK_STACK_DEPTH];
352: unsigned int mutex_stack_index;
353: unsigned int lock_stack_index;
354: unsigned mutex_count; /* XXX to be deleted XXX */
355: boolean_t kthread; /* thread is a kernel thread */
356: #endif /* MACH_LDEBUG */
357:
358: /*
359: * End of thread_shuttle proper
360: */
361:
362: /*
363: * Migration and thread_activation linkage information
364: */
365: struct thread_activation *top_act; /* "current" thr_act */
366:
367: } Thread_Shuttle;
368:
369: #define THREAD_SHUTTLE_NULL ((thread_shuttle_t)0)
370:
371: #define ith_state saved.receive.state
372: #define ith_msize saved.receive.msize
373: #define ith_kmsg saved.receive.kmsg
374: #define ith_seqno saved.receive.seqno
375: #define ith_option saved.receive.option
376: #define ith_scatter_list saved.receive.scatter_list
377: #define ith_scatter_list_size saved.receive.scatter_list_size
378: #define ith_other saved.other
379:
380: extern thread_act_t active_kloaded[NCPUS]; /* "" kernel-loaded acts */
381: extern vm_offset_t active_stacks[NCPUS]; /* active kernel stacks */
382: extern vm_offset_t kernel_stack[NCPUS];
383:
384: decl_mutex_data(extern,funnel_lock);
385:
386: #ifndef MACHINE_STACK_STASH
387: /*
388: * MD Macro to fill up global stack state,
389: * keeping the MD structure sizes + games private
390: */
391: #define MACHINE_STACK_STASH(stack) \
392: MACRO_BEGIN \
393: mp_disable_preemption(); \
394: active_stacks[cpu_number()] = (stack); \
395: kernel_stack[cpu_number()] = (stack) + KERNEL_STACK_SIZE; \
396: mp_enable_preemption(); \
397: MACRO_END
398: #endif /* MACHINE_STACK_STASH */
399:
400: /*
401: * Kernel-only routines
402: */
403:
404: /* Initialize thread module */
405: extern void thread_init(void);
406:
407: /* Take reference on thread (make sure it doesn't go away) */
408: extern void thread_reference(
409: thread_t thread);
410:
411: /* Release reference on thread */
412: extern void thread_deallocate(
413: thread_t thread);
414:
415: /* Set priority of calling thread */
416: extern void thread_set_own_priority(
417: int priority);
418:
419: /* Reset thread's priority */
420: extern kern_return_t thread_priority(
421: thread_act_t thr_act,
422: int priority,
423: boolean_t set_max);
424:
425: /* Reset thread's max priority */
426: extern kern_return_t thread_max_priority(
427: thread_act_t thr_act,
428: processor_set_t pset,
429: int max_priority);
430:
431: /* Reset thread's max priority while holding RPC locks */
432: extern kern_return_t thread_max_priority_locked(
433: thread_t thread,
434: processor_set_t pset,
435: int max_priority);
436:
437: /* Set a thread's priority while holding RPC locks */
438: extern kern_return_t thread_priority_locked(
439: thread_t thread,
440: int priority,
441: boolean_t set_max);
442:
443: /* Start a thread at specified routine */
444: #define thread_start(thread, start) \
445: (thread)->continuation = (start)
446:
447:
448: /* Reaps threads waiting to be destroyed */
449: extern void thread_reaper(void);
450:
451: extern boolean_t thread_not_preemptable(
452: thread_t thread);
453:
454: #if MACH_HOST
455: /* Preclude thread processor set assignement */
456: extern void thread_freeze(
457: thread_t thread);
458:
459: /* Assign thread to a processor set */
460: extern void thread_doassign(
461: thread_t thread,
462: processor_set_t new_pset,
463: boolean_t release_freeze);
464:
465: /* Allow thread processor set assignement */
466: extern void thread_unfreeze(
467: thread_t thread);
468:
469: #endif /* MACH_HOST */
470:
471: /* Insure thread always has a kernel stack */
472: extern void stack_privilege(
473: thread_t thread);
474:
475: extern void consider_thread_collect(void);
476:
477: /*
478: * Arguments to specify aggressiveness to thread halt.
479: * Can't have MUST_HALT and SAFELY at the same time.
480: */
481: #define THREAD_HALT_NORMAL 0
482: #define THREAD_HALT_MUST_HALT 1 /* no deadlock checks */
483: #define THREAD_HALT_SAFELY 2 /* result must be restartable */
484:
485: /*
486: * Macro-defined routines
487: */
488:
489: #define thread_pcb(th) ((th)->pcb)
490:
491: #define thread_lock_init(th) \
492: simple_lock_init(&(th)->lock, ETAP_THREAD_LOCK)
493: #define thread_lock(th) simple_lock(&(th)->lock)
494: #define thread_unlock(th) simple_unlock(&(th)->lock)
495:
496: #define thread_should_halt_fast(thread) \
497: (!(thread)->top_act || \
498: !(thread)->top_act->active || \
499: (thread)->top_act->ast & (AST_HALT|AST_TERMINATE))
500:
501: #define thread_should_halt(thread) thread_should_halt_fast(thread)
502:
503: #if 0 /* Gernoble */
504: /*
505: * We consider a thread not preemptable if it is marked as either
506: * suspended, waiting or halted.
507: * XXX - when scheduling framework and such is done, the
508: * thread state check can be eliminated
509: */
510: #define thread_not_preemptable(thread) \
511: (((thread)->state & (TH_WAIT|TH_SUSP)) != 0)
512:
513: #endif
514:
515: #define thread_lock_pair(ta,tb) \
516: MACRO_BEGIN \
517: if ((ta) < (tb)) { \
518: thread_lock(ta); \
519: thread_lock(tb); \
520: } \
521: else { \
522: thread_lock(tb); \
523: thread_lock(ta); \
524: } \
525: MACRO_END
526:
527: #define thread_unlock_pair(ta,tb) \
528: MACRO_BEGIN \
529: if ((ta) < (tb)) { \
530: thread_unlock(tb); \
531: thread_unlock(ta); \
532: } \
533: else { \
534: thread_unlock(ta); \
535: thread_unlock (tb); \
536: } \
537: MACRO_END
538:
539: #define rpc_lock_init(th) mutex_init(&(th)->rpc_lock, ETAP_THREAD_RPC)
540: #define rpc_lock(th) mutex_lock(&(th)->rpc_lock)
541: #define rpc_lock_try(th) mutex_try(&(th)->rpc_lock)
542: #define rpc_unlock(th) mutex_unlock(&(th)->rpc_lock)
543:
544: /*
545: * Lock to cover wake_active only; like thread_lock(), is taken
546: * at splsched(). Used to avoid calling into scheduler with a
547: * thread_lock() held. Precedes thread_lock() (and other scheduling-
548: * related locks) in the system lock ordering.
549: */
550: #define wake_lock_init(th) \
551: simple_lock_init(&(th)->wake_lock, ETAP_THREAD_WAKE)
552: #define wake_lock(th) simple_lock(&(th)->wake_lock)
553: #define wake_unlock(th) simple_unlock(&(th)->wake_lock)
554:
555: static __inline__ vm_offset_t current_stack(void);
556: static __inline__ vm_offset_t
557: current_stack(void)
558: {
559: vm_offset_t ret;
560:
561: mp_disable_preemption();
562: ret = active_stacks[cpu_number()];
563: mp_enable_preemption();
564: return ret;
565: }
566:
567:
568: extern void pcb_module_init(void);
569:
570: extern void pcb_init(
571: thread_act_t thr_act);
572:
573: extern void pcb_terminate(
574: thread_act_t thr_act);
575:
576: extern void pcb_collect(
577: thread_act_t thr_act);
578:
579: extern void pcb_user_to_kernel(
580: thread_act_t thr_act);
581:
582: extern kern_return_t thread_setstatus(
583: thread_act_t thr_act,
584: int flavor,
585: thread_state_t tstate,
586: mach_msg_type_number_t count);
587:
588: extern kern_return_t thread_getstatus(
589: thread_act_t thr_act,
590: int flavor,
591: thread_state_t tstate,
592: mach_msg_type_number_t *count);
593:
594: extern boolean_t stack_alloc_try(
595: thread_t thread,
596: void (*continuation)(void));
597:
598: /* This routine now used only internally */
599: extern kern_return_t thread_info_shuttle(
600: thread_act_t thr_act,
601: thread_flavor_t flavor,
602: thread_info_t thread_info_out,
603: mach_msg_type_number_t *thread_info_count);
604:
605: extern void thread_user_to_kernel(
606: thread_t thread);
607:
608: /* Machine-dependent routines */
609: extern void thread_machine_init(void);
610:
611: extern void thread_machine_set_current(
612: thread_t thread );
613:
614: extern kern_return_t thread_machine_create(
615: thread_t thread,
616: thread_act_t thr_act,
617: void (*start_pos)(void));
618:
619: extern void thread_set_syscall_return(
620: thread_t thread,
621: kern_return_t retval);
622:
623: extern void thread_machine_destroy(
624: thread_t thread );
625:
626: extern void thread_machine_flush(
627: thread_act_t thr_act);
628:
629: extern thread_t kernel_thread_with_attributes(
630: task_t task,
631: sp_attributes_t attributes,
632: void (*start_at)(void),
633: boolean_t start_running);
634:
635: #else /* !MACH_KERNEL_PRIVATE */
636:
637: extern boolean_t thread_should_halt(thread_t);
638:
639: #endif /* !MACH_KERNEL_PRIVATE */
640:
641: extern thread_t kernel_thread(
642: task_t task,
643: void (*start)(void));
644:
645: extern void thread_terminate_self(void);
646:
647: extern boolean_t thread_get_funneled(void);
648:
649: extern boolean_t thread_set_funneled(
650: boolean_t funneled);
651:
652: extern void thread_set_cont_arg(int);
653:
654: extern int thread_get_cont_arg(void);
655:
656: /* JMM - These are only temporary */
657: extern boolean_t is_thread_running(thread_t); /* True is TH_RUN */
658: extern boolean_t is_thread_idle(thread_t); /* True is TH_IDLE */
659: extern event_t get_thread_waitevent(thread_t);
660: extern kern_return_t get_thread_waitresult(thread_t);
661:
662: #endif /* _KERN_THREAD_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.