]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/thread.h
xnu-201.tar.gz
[apple/xnu.git] / osfmk / kern / thread.h
CommitLineData
1c79356b
A
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 Software.Distribution@CS.CMU.EDU
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 csl-dist@cs.utah.edu 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 */
0b4e3aa0 134#define THREAD_UNINT 0 /* not interruptible */
1c79356b 135#define THREAD_INTERRUPTIBLE 1 /* may not be restartable */
0b4e3aa0 136#define THREAD_ABORTSAFE 2 /* abortable safely */
1c79356b
A
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 <mach_lock_mon.h>
144#include <mach_ldebug.h>
145
146#include <mach/port.h>
147#include <kern/ast.h>
148#include <kern/cpu_number.h>
149#include <kern/queue.h>
150#include <kern/time_out.h>
151#include <kern/timer.h>
152#include <kern/lock.h>
153#include <kern/sched.h>
154#include <kern/sched_prim.h>
155#include <kern/thread_pool.h>
156#include <kern/thread_call.h>
157#include <kern/timer_call.h>
158#include <kern/task.h>
159#include <ipc/ipc_kmsg.h>
160#include <machine/thread.h>
161
0b4e3aa0 162struct thread_shuttle {
1c79356b
A
163 /*
164 * Beginning of thread_shuttle proper. When the thread is on
165 * a wait queue, these three fields are in treated as an un-
166 * official union with a wait_queue_element. If you change
167 * these, you must change that definition as well.
168 */
0b4e3aa0
A
169 queue_chain_t links; /* current run/wait queue links */
170 run_queue_t runq; /* run queue p is on SEE BELOW */
171 int whichq; /* which queue level p is on */
1c79356b
A
172/*
173 * NOTE: The runq field in the thread structure has an unusual
174 * locking protocol. If its value is RUN_QUEUE_NULL, then it is
175 * locked by the thread_lock, but if its value is something else
176 * (i.e. a run_queue) then it is locked by that run_queue's lock.
177 */
178
179 /* Thread bookkeeping */
0b4e3aa0 180 queue_chain_t pset_threads; /* list of all shuttles in proc set */
1c79356b 181
0b4e3aa0
A
182 /* Synchronization */
183 decl_simple_lock_data(,lock) /* scheduling lock (thread_lock()) */
184 decl_simple_lock_data(,wake_lock) /* covers wake_active (wake_lock())*/
185 decl_mutex_data(,rpc_lock) /* RPC lock (rpc_lock()) */
186 int ref_count; /* number of references to me */
1c79356b 187
0b4e3aa0
A
188 vm_offset_t kernel_stack;
189 vm_offset_t stack_privilege; /* reserved kernel stack */
1c79356b
A
190
191 /* Blocking information */
0b4e3aa0 192 int reason; /* why we blocked */
1c79356b 193
0b4e3aa0
A
194 event_t wait_event; /* event we are waiting on */
195 kern_return_t wait_result; /* outcome of wait -
196 * may be examined by this thread
197 * WITHOUT locking */
198
199 wait_queue_t wait_queue; /* wait queue we are currently on */
200 queue_chain_t wait_link; /* event's wait queue link */
1c79356b 201
0b4e3aa0
A
202 boolean_t wake_active; /* Someone is waiting for this
203 * thread to become suspended */
204
205 boolean_t interruptible; /* Thread is "interruptible" */
206
207 /* Thread state: */
208 int state;
1c79356b
A
209/*
210 * Thread states [bits or'ed]
211 */
212#define TH_WAIT 0x01 /* thread is queued for waiting */
213#define TH_SUSP 0x02 /* thread has been asked to stop */
214#define TH_RUN 0x04 /* thread is running or on runq */
215#define TH_UNINT 0x08 /* thread is waiting uninteruptibly */
216#define TH_HALTED 0x10 /* thread is halted at clean point ? */
217
218#define TH_ABORT 0x20 /* abort interruptible waits */
1c79356b
A
219
220#define TH_IDLE 0x80 /* thread is an idle thread */
221
222#define TH_SCHED_STATE (TH_WAIT|TH_SUSP|TH_RUN|TH_UNINT)
223
224#define TH_STACK_HANDOFF 0x0100 /* thread has no kernel stack */
0b4e3aa0
A
225#define TH_STACK_ALLOC 0x0200 /* thread is waiting for kernel stack */
226#define TH_STACK_STATE (TH_STACK_HANDOFF | TH_STACK_ALLOC)
1c79356b
A
227
228#define TH_TERMINATE 0x0400 /* thread is terminating */
229
230 /* Stack handoff information */
0b4e3aa0 231 void (*continuation)(void); /* re-start here next dispatch */
1c79356b
A
232
233 /* Scheduling information */
234 integer_t importance; /* task-relative importance */
235 integer_t sched_mode; /* scheduling mode bits */
0b4e3aa0
A
236#define TH_MODE_REALTIME 0x0001
237#define TH_MODE_TIMESHARE 0x0002
238#define TH_MODE_FAILSAFE 0x0004
239#define TH_MODE_POLLDEPRESS 0x0008
240 integer_t safe_mode; /* saved mode during fail-safe */
1c79356b 241 struct { /* see mach/thread_policy.h */
0b4e3aa0
A
242 uint32_t period;
243 uint32_t computation;
244 uint32_t constraint;
1c79356b
A
245 boolean_t preemptible;
246 } realtime;
247
248 integer_t priority; /* base priority */
249 integer_t sched_pri; /* scheduled (current) priority */
250 integer_t depress_priority; /* priority to restore */
251 integer_t max_priority;
0b4e3aa0
A
252 integer_t task_priority; /* copy of task base priority */
253
254 uint32_t current_quantum; /* duration of current quantum */
255
256 /* Fail-safe computation since last unblock or qualifying yield */
257 uint64_t metered_computation;
258 uint64_t computation_epoch;
1c79356b
A
259
260 natural_t cpu_usage; /* exp. decaying cpu usage [%cpu] */
0b4e3aa0 261 natural_t cpu_delta; /* cpu usage since last update */
1c79356b 262 natural_t sched_usage; /* load-weighted cpu usage [sched] */
0b4e3aa0
A
263 natural_t sched_delta; /* weighted cpu usage since update */
264 natural_t sched_stamp; /* when priority was updated */
265 natural_t sleep_stamp; /* when entered TH_WAIT state */
266 natural_t safe_release; /* when to release fail-safe */
1c79356b
A
267
268 /* VM global variables */
0b4e3aa0
A
269 boolean_t vm_privilege; /* can use reserved memory? */
270 vm_offset_t recover; /* page fault recovery (copyin/out) */
1c79356b
A
271
272 /* IPC data structures */
273
274 struct ipc_kmsg_queue ith_messages;
275
276 mach_port_t ith_mig_reply; /* reply port for mig */
277 mach_port_t ith_rpc_reply; /* reply port for kernel RPCs */
278
279 /* Various bits of stashed state */
280 union {
281 struct {
0b4e3aa0
A
282 mach_msg_return_t state; /* receive state */
283 ipc_object_t object; /* object received on */
284 mach_msg_header_t *msg; /* receive buffer pointer */
285 mach_msg_size_t msize; /* max size for recvd msg */
286 mach_msg_option_t option; /* options for receive */
287 mach_msg_size_t slist_size; /* scatter list size */
288 struct ipc_kmsg *kmsg; /* received message */
289 mach_port_seqno_t seqno; /* seqno of recvd message */
290 void (*continuation)(mach_msg_return_t);
291 } receive;
1c79356b 292 struct {
0b4e3aa0
A
293 struct semaphore *waitsemaphore; /* semaphore ref */
294 struct semaphore *signalsemaphore; /* semaphore ref */
295 int options; /* semaphore options */
296 kern_return_t result; /* primary result */
297 void (*continuation)(kern_return_t);
298 } sema;
1c79356b 299 struct {
0b4e3aa0
A
300 int option; /* switch option */
301 } swtch;
302 int misc; /* catch-all for other state */
303 } saved;
1c79356b
A
304
305 /* Timing data structures */
0b4e3aa0
A
306 timer_data_t user_timer; /* user mode timer */
307 timer_data_t system_timer; /* system mode timer */
308 timer_save_data_t user_timer_save; /* saved user timer value */
309 timer_save_data_t system_timer_save; /* saved system timer value */
1c79356b
A
310
311 /* Timed wait expiration */
312 timer_call_data_t wait_timer;
313 integer_t wait_timer_active;
314 boolean_t wait_timer_is_set;
315
316 /* Priority depression expiration */
0b4e3aa0
A
317 timer_call_data_t depress_timer;
318 integer_t depress_timer_active;
1c79356b
A
319
320 /* Ast/Halt data structures */
0b4e3aa0
A
321 boolean_t active; /* thread is active */
322
323 int at_safe_point; /* thread_abort_safely allowed */
1c79356b
A
324
325 /* Processor data structures */
0b4e3aa0
A
326 processor_set_t processor_set; /* assigned processor set */
327 processor_t bound_processor; /* bound to processor ?*/
1c79356b 328#if MACH_HOST
0b4e3aa0
A
329 boolean_t may_assign; /* may assignment change? */
330 boolean_t assign_active; /* waiting for may_assign */
1c79356b
A
331#endif /* MACH_HOST */
332
0b4e3aa0
A
333 processor_t last_processor; /* processor last ran on */
334
335 /* Non-reentrancy funnel */
336 struct funnel_lock *funnel_lock;
337 int funnel_state;
338#define TH_FN_OWNED 0x1 /* we own the funnel */
339#define TH_FN_REFUNNEL 0x2 /* re-acquire funnel on dispatch */
340
341/* BEGIN TRACING/DEBUG */
1c79356b 342
1c79356b 343#if MACH_LOCK_MON
0b4e3aa0 344 unsigned lock_stack; /* number of locks held */
1c79356b 345#endif /* MACH_LOCK_MON */
1c79356b 346
0b4e3aa0
A
347#if ETAP_EVENT_MONITOR
348 int etap_reason; /* real reason why we blocked */
349 boolean_t etap_trace; /* ETAP trace status */
350#endif /* ETAP_EVENT_MONITOR */
351
1c79356b
A
352#if MACH_LDEBUG
353 /*
354 * Debugging: track acquired mutexes and locks.
355 * Because a thread can block while holding such
356 * synchronizers, we think of the thread as
357 * "owning" them.
358 */
359#define MUTEX_STACK_DEPTH 20
360#define LOCK_STACK_DEPTH 20
0b4e3aa0
A
361 mutex_t *mutex_stack[MUTEX_STACK_DEPTH];
362 lock_t *lock_stack[LOCK_STACK_DEPTH];
363 unsigned int mutex_stack_index;
364 unsigned int lock_stack_index;
365 unsigned mutex_count; /* XXX to be deleted XXX */
366 boolean_t kthread; /* thread is a kernel thread */
1c79356b
A
367#endif /* MACH_LDEBUG */
368
0b4e3aa0 369/* END TRACING/DEBUG */
1c79356b 370
0b4e3aa0
A
371 /* Migration and thread_activation linkage */
372 struct thread_activation *top_act; /* "current" thr_act */
373};
1c79356b
A
374
375#define THREAD_SHUTTLE_NULL ((thread_shuttle_t)0)
376
377#define ith_state saved.receive.state
378#define ith_object saved.receive.object
379#define ith_msg saved.receive.msg
380#define ith_msize saved.receive.msize
381#define ith_option saved.receive.option
382#define ith_scatter_list_size saved.receive.slist_size
383#define ith_continuation saved.receive.continuation
384#define ith_kmsg saved.receive.kmsg
385#define ith_seqno saved.receive.seqno
386
387#define sth_waitsemaphore saved.sema.waitsemaphore
388#define sth_signalsemaphore saved.sema.signalsemaphore
389#define sth_options saved.sema.options
390#define sth_result saved.sema.result
391#define sth_continuation saved.sema.continuation
392
0b4e3aa0
A
393struct funnel_lock {
394 int fnl_type; /* funnel type */
395 mutex_t *fnl_mutex; /* underlying mutex for the funnel */
396 void * fnl_mtxholder; /* thread (last)holdng mutex */
397 void * fnl_mtxrelease; /* thread (last)releasing mutex */
398 mutex_t *fnl_oldmutex; /* Mutex before collapsing split funnel */
399};
400
401typedef struct funnel_lock funnel_t;
402
1c79356b
A
403extern thread_act_t active_kloaded[NCPUS]; /* "" kernel-loaded acts */
404extern vm_offset_t active_stacks[NCPUS]; /* active kernel stacks */
405extern vm_offset_t kernel_stack[NCPUS];
406
407#ifndef MACHINE_STACK_STASH
408/*
409 * MD Macro to fill up global stack state,
410 * keeping the MD structure sizes + games private
411 */
412#define MACHINE_STACK_STASH(stack) \
413MACRO_BEGIN \
414 mp_disable_preemption(); \
415 active_stacks[cpu_number()] = (stack); \
416 kernel_stack[cpu_number()] = (stack) + KERNEL_STACK_SIZE; \
417 mp_enable_preemption(); \
418MACRO_END
419#endif /* MACHINE_STACK_STASH */
420
421/*
422 * Kernel-only routines
423 */
424
425/* Initialize thread module */
426extern void thread_init(void);
427
428/* Take reference on thread (make sure it doesn't go away) */
429extern void thread_reference(
430 thread_t thread);
431
432/* Release reference on thread */
433extern void thread_deallocate(
434 thread_t thread);
435
0b4e3aa0
A
436/* Set task priority of member thread */
437extern void thread_task_priority(
438 thread_t thread,
439 integer_t priority,
440 integer_t max_priority);
1c79356b
A
441
442/* Start a thread at specified routine */
443#define thread_start(thread, start) \
444 (thread)->continuation = (start)
445
446
447/* Reaps threads waiting to be destroyed */
448extern void thread_reaper(void);
449
450
451#if MACH_HOST
452/* Preclude thread processor set assignement */
453extern void thread_freeze(
454 thread_t thread);
455
456/* Assign thread to a processor set */
457extern void thread_doassign(
458 thread_t thread,
459 processor_set_t new_pset,
460 boolean_t release_freeze);
461
462/* Allow thread processor set assignement */
463extern void thread_unfreeze(
464 thread_t thread);
465
466#endif /* MACH_HOST */
467
468/* Insure thread always has a kernel stack */
469extern void stack_privilege(
470 thread_t thread);
471
472extern void consider_thread_collect(void);
473
474/*
475 * Arguments to specify aggressiveness to thread halt.
476 * Can't have MUST_HALT and SAFELY at the same time.
477 */
478#define THREAD_HALT_NORMAL 0
479#define THREAD_HALT_MUST_HALT 1 /* no deadlock checks */
480#define THREAD_HALT_SAFELY 2 /* result must be restartable */
481
482/*
483 * Macro-defined routines
484 */
485
486#define thread_pcb(th) ((th)->pcb)
487
488#define thread_lock_init(th) \
489 simple_lock_init(&(th)->lock, ETAP_THREAD_LOCK)
490#define thread_lock(th) simple_lock(&(th)->lock)
491#define thread_unlock(th) simple_unlock(&(th)->lock)
492
493#define thread_should_halt_fast(thread) \
494 (!(thread)->top_act || \
495 !(thread)->top_act->active || \
496 (thread)->top_act->ast & (AST_HALT|AST_TERMINATE))
497
498#define thread_should_halt(thread) thread_should_halt_fast(thread)
499
500#define rpc_lock_init(th) mutex_init(&(th)->rpc_lock, ETAP_THREAD_RPC)
501#define rpc_lock(th) mutex_lock(&(th)->rpc_lock)
502#define rpc_lock_try(th) mutex_try(&(th)->rpc_lock)
503#define rpc_unlock(th) mutex_unlock(&(th)->rpc_lock)
504
505/*
506 * Lock to cover wake_active only; like thread_lock(), is taken
507 * at splsched(). Used to avoid calling into scheduler with a
508 * thread_lock() held. Precedes thread_lock() (and other scheduling-
509 * related locks) in the system lock ordering.
510 */
511#define wake_lock_init(th) \
512 simple_lock_init(&(th)->wake_lock, ETAP_THREAD_WAKE)
513#define wake_lock(th) simple_lock(&(th)->wake_lock)
514#define wake_unlock(th) simple_unlock(&(th)->wake_lock)
515
516static __inline__ vm_offset_t current_stack(void);
517static __inline__ vm_offset_t
518current_stack(void)
519{
520 vm_offset_t ret;
521
522 mp_disable_preemption();
523 ret = active_stacks[cpu_number()];
524 mp_enable_preemption();
525 return ret;
526}
527
528
529extern void pcb_module_init(void);
530
531extern void pcb_init(
532 thread_act_t thr_act);
533
534extern void pcb_terminate(
535 thread_act_t thr_act);
536
537extern void pcb_collect(
538 thread_act_t thr_act);
539
540extern void pcb_user_to_kernel(
541 thread_act_t thr_act);
542
543extern kern_return_t thread_setstatus(
544 thread_act_t thr_act,
545 int flavor,
546 thread_state_t tstate,
547 mach_msg_type_number_t count);
548
549extern kern_return_t thread_getstatus(
550 thread_act_t thr_act,
551 int flavor,
552 thread_state_t tstate,
553 mach_msg_type_number_t *count);
554
555extern boolean_t stack_alloc_try(
556 thread_t thread,
557 void (*start_pos)(thread_t));
558
559/* This routine now used only internally */
560extern kern_return_t thread_info_shuttle(
561 thread_act_t thr_act,
562 thread_flavor_t flavor,
563 thread_info_t thread_info_out,
564 mach_msg_type_number_t *thread_info_count);
565
566extern void thread_user_to_kernel(
567 thread_t thread);
568
569/* Machine-dependent routines */
570extern void thread_machine_init(void);
571
572extern void thread_machine_set_current(
573 thread_t thread );
574
575extern kern_return_t thread_machine_create(
576 thread_t thread,
577 thread_act_t thr_act,
578 void (*start_pos)(thread_t));
579
580extern void thread_set_syscall_return(
581 thread_t thread,
582 kern_return_t retval);
583
584extern void thread_machine_destroy(
585 thread_t thread );
586
587extern void thread_machine_flush(
588 thread_act_t thr_act);
589
590extern thread_t kernel_thread_with_priority(
591 task_t task,
592 integer_t priority,
593 void (*start)(void),
0b4e3aa0 594 boolean_t alloc_stack,
1c79356b
A
595 boolean_t start_running);
596
597extern void funnel_lock(funnel_t *);
598
599extern void funnel_unlock(funnel_t *);
600
601#else /* !MACH_KERNEL_PRIVATE */
602
0b4e3aa0 603typedef struct funnel_lock funnel_t;
1c79356b
A
604
605extern boolean_t thread_should_halt(thread_t);
606
607#endif /* !MACH_KERNEL_PRIVATE */
608
609#define THR_FUNNEL_NULL (funnel_t *)0
610
611extern thread_t kernel_thread(
612 task_t task,
613 void (*start)(void));
614
615extern void thread_terminate_self(void);
616
617extern funnel_t * funnel_alloc(int);
618
619extern funnel_t * thread_funnel_get(void);
620
621extern boolean_t thread_funnel_set(funnel_t * fnl, boolean_t funneled);
622
623extern boolean_t thread_funnel_merge(funnel_t * fnl, funnel_t * otherfnl);
624
625extern void thread_set_cont_arg(int);
626
627extern int thread_get_cont_arg(void);
628
629/* JMM - These are only temporary */
630extern boolean_t is_thread_running(thread_t); /* True is TH_RUN */
631extern boolean_t is_thread_idle(thread_t); /* True is TH_IDLE */
632extern event_t get_thread_waitevent(thread_t);
633extern kern_return_t get_thread_waitresult(thread_t);
634
635#endif /* _KERN_THREAD_H_ */