Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
/*
 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 * @OSF_FREE_COPYRIGHT@
 */
/* 
 * Mach Operating System
 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*
 */
/*
 *	File:	thread.h
 *	Author:	Avadis Tevanian, Jr.
 *
 *	This file contains the structure definitions for threads.
 *
 */
/*
 * Copyright (c) 1993 The University of Utah and
 * the Computer Systems Laboratory (CSL).  All rights reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
 * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
 * improvements that they make and grant CSL redistribution rights.
 *
 */

#ifndef	_KERN_THREAD_H_
#define _KERN_THREAD_H_

#include <mach/kern_return.h>
#include <mach/mach_types.h>
#include <mach/message.h>
#include <mach/boolean.h>
#include <mach/vm_types.h>
#include <mach/vm_prot.h>
#include <mach/thread_info.h>
#include <mach/thread_status.h>

#include <kern/cpu_data.h>		/* for current_thread */
#include <kern/kern_types.h>

#include <ipc/ipc_types.h>

/*
 * Logically, a thread of control consists of two parts:
 *
 *	a thread_shuttle, which may migrate due to resource contention
 * and
 *	a thread_activation, which remains attached to a task.
 *
 * The thread_shuttle contains scheduling info, accounting info,
 * and links to the thread_activation within which the shuttle is
 * currently operating.
 *
 * It might make sense to have the thread_shuttle be a proper sub-structure
 * of the thread, with the thread containing links to both the shuttle and
 * activation.  In order to reduce the scope and complexity of source
 * changes and the overhead of maintaining these linkages, we have subsumed
 * the shuttle into the thread, calling it a thread_shuttle.
 *
 * User accesses to threads always come in via the user's thread port,
 * which gets translated to a pointer to the target thread_activation.
 */
#include <sys/appleapiopts.h>

#ifdef	__APPLE_API_PRIVATE

#ifdef	MACH_KERNEL_PRIVATE

#include <cpus.h>
#include <hw_footprint.h>
#include <mach_host.h>
#include <mach_prof.h>
#include <mach_lock_mon.h>
#include <mach_ldebug.h>

#include <mach/port.h>
#include <kern/ast.h>
#include <kern/cpu_number.h>
#include <kern/queue.h>
#include <kern/time_out.h>
#include <kern/timer.h>
#include <kern/lock.h>
#include <kern/sched.h>
#include <kern/sched_prim.h>
#include <kern/thread_call.h>
#include <kern/timer_call.h>
#include <kern/task.h>
#include <ipc/ipc_kmsg.h>
#include <machine/thread.h>

/*
 * Kernel accesses intended to effect the entire thread, typically use
 * a pointer to the thread_shuttle (current_thread()) as the target of
 * their operations.  This makes sense given that we have subsumed the
 * shuttle into the thread_shuttle, eliminating one set of linkages.
 * Operations effecting only the shuttle may use a thread_shuttle_t
 * to indicate this.
 *
 * The current_act() macro returns a pointer to the current thread_act, while
 * the current_thread() macro returns a pointer to the currently active
 * thread_shuttle (representing the thread in its entirety).
 */
struct thread_shuttle {
	/*
	 *	NOTE:	The runq field in the thread structure has an unusual
	 *	locking protocol.  If its value is RUN_QUEUE_NULL, then it is
	 *	locked by the thread_lock, but if its value is something else
	 *	(i.e. a run_queue) then it is locked by that run_queue's lock.
	 *
	 *	Beginning of thread_shuttle proper.  When the thread is on
	 *	a wait queue, these first three fields are treated as an un-
	 *	official union with a wait_queue_element.  If you change
	 *	these, you must change that definition as well (wait_queue.h).
	 */
  	/* Items examined often, modified infrequently */
	queue_chain_t	links;				/* run/wait queue links */
	run_queue_t		runq;				/* run queue thread is on SEE BELOW */
	wait_queue_t	wait_queue;			/* wait queue we are currently on */
	event64_t		wait_event;			/* wait queue event */
	thread_act_t	top_act;			/* "current" thr_act */
	uint32_t							/* Only set by thread itself */
						interrupt_level:2,	/* interrupts/aborts allowed */
						vm_privilege:1,		/* can use reserved memory? */
						active_callout:1,	/* an active callout */
						:0;


	/* Data updated during assert_wait/thread_wakeup */
	decl_simple_lock_data(,lock)		/* scheduling lock (thread_lock()) */
	decl_simple_lock_data(,wake_lock)	/* covers wake_active (wake_lock())*/
	boolean_t			wake_active;	/* Someone is waiting for this */
	int					at_safe_point;	/* thread_abort_safely allowed */
	ast_t				reason;			/* why we blocked */
	wait_result_t		wait_result;	/* outcome of wait -
										 * may be examined by this thread
										 * WITHOUT locking */
	thread_roust_t 		roust;			/* routine to roust it after wait */
	thread_continue_t	continuation;	/* resume here next dispatch */

	/* Data updated/used in thread_invoke */
    struct funnel_lock	*funnel_lock;		/* Non-reentrancy funnel */
    int				    funnel_state;
#define TH_FN_OWNED			0x1				/* we own the funnel */
#define TH_FN_REFUNNEL		0x2				/* re-acquire funnel on dispatch */

	vm_offset_t     	kernel_stack;		/* current kernel stack */
	vm_offset_t			stack_privilege;	/* reserved kernel stack */

	/* Thread state: */
	int					state;
/*
 *	Thread states [bits or'ed]
 */
#define TH_WAIT			0x01			/* thread is queued for waiting */
#define TH_SUSP			0x02			/* thread has been asked to stop */
#define TH_RUN			0x04			/* thread is running or on runq */
#define TH_UNINT		0x08			/* thread is waiting uninteruptibly */
#define	TH_TERMINATE	0x10			/* thread is halting at termination */

#define TH_ABORT		0x20	/* abort interruptible waits */
#define TH_ABORT_SAFELY	0x40	/* ... but only those at safe point */

#define TH_IDLE			0x80			/* thread is an idle thread */

#define	TH_SCHED_STATE	(TH_WAIT|TH_SUSP|TH_RUN|TH_UNINT)

#define	TH_STACK_HANDOFF	0x0100		/* thread has no kernel stack */
#define	TH_STACK_ALLOC		0x0200		/* waiting for stack allocation */
#define	TH_STACK_STATE	(TH_STACK_HANDOFF | TH_STACK_ALLOC)

	/* Scheduling information */
	integer_t			sched_mode;			/* scheduling mode bits */
#define TH_MODE_REALTIME		0x0001		/* time constraints supplied */
#define TH_MODE_TIMESHARE		0x0002		/* use timesharing algorithm */
#define TH_MODE_PREEMPT			0x0004		/* can preempt kernel contexts */
#define TH_MODE_FAILSAFE		0x0008		/* fail-safe has tripped */
#define	TH_MODE_PROMOTED		0x0010		/* sched pri has been promoted */
#define	TH_MODE_FORCEDPREEMPT	0x0020		/* force setting of mode PREEMPT */
#define	TH_MODE_DEPRESS			0x0040		/* normal depress yield */
#define TH_MODE_POLLDEPRESS		0x0080		/* polled depress yield */
#define TH_MODE_ISDEPRESSED		(TH_MODE_DEPRESS | TH_MODE_POLLDEPRESS)

	integer_t			sched_pri;			/* scheduled (current) priority */
	integer_t			priority;			/* base priority */
	integer_t			max_priority;		/* max base priority */
	integer_t			task_priority;		/* copy of task base priority */

	integer_t			promotions;			/* level of promotion */
	integer_t			pending_promoter_index;
	void				*pending_promoter[2];

	integer_t			importance;			/* task-relative importance */

											/* time constraint parameters */
	struct {								/* see mach/thread_policy.h */
		uint32_t			period;
		uint32_t			computation;
		uint32_t			constraint;
		boolean_t			preemptible;
	}					realtime;

	uint32_t			current_quantum;	/* duration of current quantum */

  /* Data used during setrun/dispatch */
	timer_data_t		system_timer;		/* system mode timer */
	processor_set_t		processor_set;		/* assigned processor set */
	processor_t			bound_processor;	/* bound to a processor? */
	processor_t			last_processor;		/* processor last dispatched on */
	uint64_t			last_switch;		/* time of last context switch */

	/* Fail-safe computation since last unblock or qualifying yield */
	uint64_t			computation_metered;
	uint64_t			computation_epoch;
	integer_t			safe_mode;		/* saved mode during fail-safe */
	natural_t			safe_release;	/* when to release fail-safe */

  /* Used in priority computations */
	natural_t			sched_stamp;	/* when priority was updated */
	natural_t			cpu_usage;		/* exp. decaying cpu usage [%cpu] */
	natural_t			cpu_delta;		/* cpu usage since last update */
	natural_t			sched_usage;	/* load-weighted cpu usage [sched] */
	natural_t			sched_delta;	/* weighted cpu usage since update */
	natural_t			sleep_stamp;	/* when entered TH_WAIT state */

	/* Timing data structures */
	timer_data_t			user_timer;			/* user mode timer */
	timer_save_data_t		system_timer_save;	/* saved system timer value */
	timer_save_data_t		user_timer_save;	/* saved user timer value */

	/* Timed wait expiration */
	timer_call_data_t		wait_timer;
	integer_t				wait_timer_active;
	boolean_t				wait_timer_is_set;

	/* Priority depression expiration */
	timer_call_data_t		depress_timer;
	integer_t				depress_timer_active;

	/* Various bits of stashed state */
	union {
		struct {
		  	mach_msg_return_t	state;		/* receive state */
		  	ipc_object_t		object;		/* object received on */
		  	mach_msg_header_t	*msg;		/* receive buffer pointer */
			mach_msg_size_t		msize;		/* max size for recvd msg */
		  	mach_msg_option_t	option;		/* options for receive */
		  	mach_msg_size_t		slist_size;	/* scatter list size */
			struct ipc_kmsg		*kmsg;		/* received message */
			mach_port_seqno_t	seqno;		/* seqno of recvd message */
			mach_msg_continue_t	continuation;
		} receive;
		struct {
			struct semaphore	*waitsemaphore;  	/* semaphore ref */
			struct semaphore	*signalsemaphore;	/* semaphore ref */
			int					options;			/* semaphore options */
			kern_return_t		result;				/* primary result */
			mach_msg_continue_t continuation;
		} sema;
	  	struct {
			int					option;		/* switch option */
		} swtch;
		int						misc;		/* catch-all for other state */
	} saved;

	/* IPC data structures */
	struct ipc_kmsg_queue ith_messages;
	mach_port_t ith_mig_reply;			/* reply port for mig */
	mach_port_t ith_rpc_reply;			/* reply port for kernel RPCs */

	/* Ast/Halt data structures */
	boolean_t			active;			/* thread is active */
	vm_offset_t			recover;		/* page fault recover(copyin/out) */
	int					ref_count;		/* number of references to me */

	/* Processor set info */
	queue_chain_t		pset_threads;	/* list of all shuttles in pset */
#if	MACH_HOST
	boolean_t			may_assign;		/* may assignment change? */
	boolean_t			assign_active;	/* waiting for may_assign */
#endif	/* MACH_HOST */

/* BEGIN TRACING/DEBUG */

#if	MACH_LOCK_MON
	unsigned			lock_stack;			/* number of locks held */
#endif  /* MACH_LOCK_MON */

#if	ETAP_EVENT_MONITOR
	int					etap_reason;		/* real reason why we blocked */
	boolean_t			etap_trace;			/* ETAP trace status */
#endif	/* ETAP_EVENT_MONITOR */

#if	MACH_LDEBUG
	/*
	 *	Debugging:  track acquired mutexes and locks.
	 *	Because a thread can block while holding such
	 *	synchronizers, we think of the thread as
	 *	"owning" them.
	 */
#define	MUTEX_STACK_DEPTH	20
#define	LOCK_STACK_DEPTH	20
	mutex_t				*mutex_stack[MUTEX_STACK_DEPTH];
	lock_t				*lock_stack[LOCK_STACK_DEPTH];
	unsigned int		mutex_stack_index;
	unsigned int		lock_stack_index;
	unsigned			mutex_count;		/* XXX to be deleted XXX */
#endif	/* MACH_LDEBUG */
/* END TRACING/DEBUG */

};

#define ith_state		saved.receive.state
#define ith_object		saved.receive.object
#define ith_msg			saved.receive.msg
#define ith_msize		saved.receive.msize
#define	ith_option		saved.receive.option
#define ith_scatter_list_size	saved.receive.slist_size
#define ith_continuation	saved.receive.continuation
#define ith_kmsg		saved.receive.kmsg
#define ith_seqno		saved.receive.seqno

#define sth_waitsemaphore	saved.sema.waitsemaphore
#define sth_signalsemaphore	saved.sema.signalsemaphore
#define sth_options		saved.sema.options
#define sth_result		saved.sema.result
#define sth_continuation	saved.sema.continuation

struct funnel_lock {
	int			fnl_type;			/* funnel type */
	mutex_t		*fnl_mutex;			/* underlying mutex for the funnel */
	void *		fnl_mtxholder;		/* thread (last)holdng mutex */
	void *		fnl_mtxrelease;		/* thread (last)releasing mutex */
	mutex_t		*fnl_oldmutex;		/* Mutex before collapsing split funnel */
};

typedef struct funnel_lock		funnel_t;

extern thread_act_t active_kloaded[NCPUS];	/* "" kernel-loaded acts */
extern vm_offset_t active_stacks[NCPUS];	/* active kernel stacks */
extern vm_offset_t kernel_stack[NCPUS];

extern	struct thread_shuttle	pageout_thread;

#ifndef MACHINE_STACK_STASH
/*
 * MD Macro to fill up global stack state,
 * keeping the MD structure sizes + games private
 */
#define MACHINE_STACK_STASH(stack)								\
MACRO_BEGIN														\
	mp_disable_preemption();									\
	active_stacks[cpu_number()] = (stack);						\
	kernel_stack[cpu_number()] = (stack) + KERNEL_STACK_SIZE;	\
	mp_enable_preemption();										\
MACRO_END
#endif	/* MACHINE_STACK_STASH */

/*
 *	Kernel-only routines
 */

/* Initialize thread module */
extern void		thread_init(void);

/* Take reference on thread (make sure it doesn't go away) */
extern void		thread_reference(
					thread_t		thread);

/* Release reference on thread */
extern void		thread_deallocate(
					thread_t		thread);

/* Set task priority of member thread */
extern void		thread_task_priority(
					thread_t		thread,
					integer_t		priority,
					integer_t		max_priority);

/* Start a thread at specified routine */
#define thread_start(thread, start)						\
					(thread)->continuation = (start)

/* Reaps threads waiting to be destroyed */
extern void		thread_reaper_init(void);


/* Insure thread always has a kernel stack */
extern void		stack_privilege(
					thread_t		thread);

extern void		consider_thread_collect(void);

/*
 *	Arguments to specify aggressiveness to thread halt.
 *	Can't have MUST_HALT and SAFELY at the same time.
 */
#define	THREAD_HALT_NORMAL	0
#define	THREAD_HALT_MUST_HALT	1	/* no deadlock checks */
#define	THREAD_HALT_SAFELY	2	/* result must be restartable */

/*
 *	Macro-defined routines
 */

#define thread_pcb(th)			((th)->pcb)

#define	thread_lock_init(th)	simple_lock_init(&(th)->lock, ETAP_THREAD_LOCK)
#define thread_lock(th)			simple_lock(&(th)->lock)
#define thread_unlock(th)		simple_unlock(&(th)->lock)
#define thread_lock_try(th)		simple_lock_try(&(th)->lock)

#define thread_should_halt_fast(thread)	\
	(!(thread)->top_act || !(thread)->top_act->active)

#define thread_should_halt(thread) thread_should_halt_fast(thread)

#define thread_reference_locked(thread) ((thread)->ref_count++)

/*
 * Lock to cover wake_active only; like thread_lock(), is taken
 * at splsched().  Used to avoid calling into scheduler with a
 * thread_lock() held.  Precedes thread_lock() (and other scheduling-
 * related locks) in the system lock ordering.
 */
#define wake_lock_init(th)					\
			simple_lock_init(&(th)->wake_lock, ETAP_THREAD_WAKE)
#define wake_lock(th)		simple_lock(&(th)->wake_lock)
#define wake_unlock(th)		simple_unlock(&(th)->wake_lock)
#define wake_lock_try(th)		simple_lock_try(&(th)->wake_lock)

static __inline__ vm_offset_t current_stack(void);
static __inline__ vm_offset_t
current_stack(void)
{
	vm_offset_t	ret;

	mp_disable_preemption();
	ret = active_stacks[cpu_number()];
	mp_enable_preemption();
	return ret;
}

extern void		pcb_module_init(void);

extern void		pcb_init(
					thread_act_t	thr_act);

extern void		pcb_terminate(
					thread_act_t	thr_act);

extern void		pcb_collect(
					thread_act_t	thr_act);

extern void		pcb_user_to_kernel(
					thread_act_t	thr_act);

extern kern_return_t	thread_setstatus(
							thread_act_t			thr_act,
							int						flavor,
							thread_state_t			tstate,
							mach_msg_type_number_t	count);

extern kern_return_t	thread_getstatus(
							thread_act_t			thr_act,
							int						flavor,
							thread_state_t			tstate,
							mach_msg_type_number_t	*count);

extern boolean_t		stack_alloc_try(
							thread_t			    thread,
							void					(*start_pos)(thread_t));

/* This routine now used only internally */
extern kern_return_t	thread_info_shuttle(
							thread_act_t			thr_act,
							thread_flavor_t			flavor,
							thread_info_t			thread_info_out,
							mach_msg_type_number_t	*thread_info_count);

/* Machine-dependent routines */
extern void		thread_machine_init(void);

extern void		thread_machine_set_current(
					thread_t		thread );

extern kern_return_t	thread_machine_create(
							thread_t			thread,
							thread_act_t		thr_act,
							void				(*start_pos)(thread_t));

extern void		thread_set_syscall_return(
					thread_t		thread,
					kern_return_t	retval);

extern void		thread_machine_destroy(
					thread_t		thread );

extern void		thread_machine_flush(
				thread_act_t thr_act);

extern thread_t     kernel_thread_with_priority(
                    task_t          task,
					integer_t		priority,
                    void            (*start)(void),
					boolean_t		alloc_stack,
                    boolean_t       start_running);

extern void			thread_terminate_self(void);

extern void 		funnel_lock(funnel_t *);

extern void 		funnel_unlock(funnel_t *);

#else	/* MACH_KERNEL_PRIVATE */

typedef struct funnel_lock		funnel_t;

extern boolean_t thread_should_halt(thread_t);

#endif	/* MACH_KERNEL_PRIVATE */

extern thread_t		kernel_thread(
						task_t		task,
						void		(*start)(void));

extern void         thread_set_cont_arg(int);

extern int          thread_get_cont_arg(void);

/* JMM - These are only temporary */
extern boolean_t	is_thread_running(thread_act_t); /* True is TH_RUN */
extern boolean_t	is_thread_idle(thread_t); /* True is TH_IDLE */
extern kern_return_t	get_thread_waitresult(thread_t);

#endif	/* __APPLE_API_PRIVATE */

#ifdef __APPLE_API_EVOLVING

#define THR_FUNNEL_NULL (funnel_t *)0

extern funnel_t *	funnel_alloc(int);

extern funnel_t *	thread_funnel_get(void);

extern boolean_t	thread_funnel_set(funnel_t * fnl, boolean_t funneled);

extern boolean_t	thread_funnel_merge(funnel_t * fnl, funnel_t * otherfnl);

#endif	/* __APPLE_API_EVOLVING */

#endif	/* _KERN_THREAD_H_ */