summaryrefslogtreecommitdiff
path: root/kern/thread.h
blob: 7106fd2d81fe34b4960599f8c57abbee9482ab24 (plain)
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
/* 
 * Mach Operating System
 * Copyright (c) 1993-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.
 *
 */

#ifndef	_KERN_THREAD_H_
#define _KERN_THREAD_H_

#include <mach/boolean.h>
#include <mach/thread_info.h>
#include <mach/thread_status.h>
#include <mach/machine/vm_types.h>
#include <mach/message.h>
#include <mach/port.h>
#include <mach/vm_prot.h>
#include <kern/ast.h>
#include <kern/cpu_number.h>
#include <kern/mach_clock.h>
#include <kern/queue.h>
#include <kern/pc_sample.h>
#include <kern/processor.h>
#include <kern/sched_prim.h>	/* event_t, continuation_t */
#include <kern/timer.h>
#include <kern/lock.h>
#include <kern/sched.h>
#include <kern/task.h>		/* for current_space(), current_map() */
#include <machine/thread.h>
#include <ipc/ipc_kmsg_queue.h>

struct thread {
	/* Run queues */
	queue_chain_t	links;		/* current run queue links */
	run_queue_t	runq;		/* run queue p is on SEE BELOW */
/*
 *	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.
 */

	/* Task information */
	task_t		task;		/* Task to which I belong */
	queue_chain_t	thread_list;	/* list of threads in task */

	/* Flags */
	/* The flags are grouped here, but documented at the original
	   position.  */
	union {
		struct {
			unsigned	state:16;
			unsigned	wake_active:1;
			unsigned	vm_privilege:1;
			unsigned	active:1;
		};
		event_t	event_key;
/* These keys can be used with thread_wakeup and friends.  */
#define TH_EV_WAKE_ACTIVE(t)	((event_t) (&(t)->event_key + 0))
#define TH_EV_STATE(t)		((event_t) (&(t)->event_key + 1))
	};

	/* Thread bookkeeping */
	queue_chain_t	pset_threads;	/* list of all threads in proc set*/

	/* Self-preservation */
	decl_simple_lock_data(,lock)
	int		ref_count;	/* number of references to me */

	/* Hardware state */
	pcb_t		pcb;		/* hardware pcb & machine state */
	vm_offset_t	kernel_stack;	/* accurate only if the thread is
					   not swapped and not executing */
	vm_offset_t	stack_privilege;/* reserved kernel stack */

	/* Swapping information */
	continuation_t	swap_func;	/* start here after swapin */

	/* Blocking information */
	event_t		wait_event;	/* event we are waiting on */
	int		suspend_count;	/* internal use only */
	kern_return_t	wait_result;	/* outcome of wait -
					   may be examined by this thread
					   WITHOUT locking */
	/* Defined above */
	/* boolean_t	wake_active;	   someone is waiting for this
					   thread to become suspended */
	/* int		state;		   Thread 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_HALTED		0x10	/* thread is halted at clean point ? */

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

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

#define	TH_SWAPPED		0x0100	/* thread has no kernel stack */
#define	TH_SW_COMING_IN		0x0200	/* thread is waiting for kernel stack */

#define	TH_SWAP_STATE	(TH_SWAPPED | TH_SW_COMING_IN)

	/* Scheduling information */
	int		priority;	/* thread's priority */
	int		max_priority;	/* maximum priority */
	int		sched_pri;	/* scheduled (computed) priority */
#if	MACH_FIXPRI
	int		sched_data;	/* for use by policy */
	int		policy;		/* scheduling policy */
#endif	/* MACH_FIXPRI */
	int		depress_priority; /* depressed from this priority */
	unsigned int	cpu_usage;	/* exp. decaying cpu usage [%cpu] */
	unsigned int	sched_usage;	/* load-weighted cpu usage [sched] */
	unsigned int	sched_stamp;	/* last time priority was updated */

	/* VM global variables */

	vm_offset_t	recover;	/* page fault recovery (copyin/out) */
	/* Defined above */
	/* boolean_t	vm_privilege;	   Can use reserved memory? */

	/* User-visible scheduling state */
	int		user_stop_count;	/* outstanding stops */

	/* IPC data structures */
	struct thread *ith_next, *ith_prev;
	mach_msg_return_t ith_state;
	union {
		mach_msg_size_t msize;		/* max size for recvd msg */
		struct ipc_kmsg *kmsg;		/* received message */
	} data;
	mach_port_seqno_t ith_seqno;		/* seqno of recvd message */

	/* This queue is used only when destroying messages:
	   it prevents nasty recursion problems when destroying one message
	   causes other messages to be destroyed.
	   This queue should always be empty under normal circumstances.
	   See ipc_kmsg_destroy() for more details.  */
	struct ipc_kmsg_queue ith_messages; 

	decl_simple_lock_data(, ith_lock_data)
	struct ipc_port *ith_self;	/* not a right, doesn't hold ref */
	struct ipc_port *ith_sself;	/* a send right */
	struct ipc_port *ith_exception;	/* a send right */

	mach_port_t ith_mig_reply;	/* reply port for mig */
	struct ipc_port *ith_rpc_reply;	/* reply port for kernel RPCs */

	/* State saved when thread's stack is discarded */
	union {
		struct {
			mach_msg_header_t *msg;
			mach_msg_option_t option;
			mach_msg_size_t rcv_size;
			mach_msg_timeout_t timeout;
			mach_port_t notify;
			struct ipc_object *object;
			struct ipc_mqueue *mqueue;
		} receive;
		struct {
			struct ipc_port *port;
			int exc;
			int code;
			int subcode;
		} exception;
		void *other;		/* catch-all for other state */
	} saved;

	/* Timing data structures */
	timer_data_t	user_timer;	/* user mode timer */
	timer_data_t	system_timer;	/* system mode timer */
	timer_save_data_t user_timer_save;  /* saved user timer value */
	timer_save_data_t system_timer_save;  /* saved sys timer val. */
	unsigned int	cpu_delta;	/* cpu usage since last update */
	unsigned int	sched_delta;	/* weighted cpu usage since update */

	/* Creation time stamp */
	time_value_t	creation_time;

	/* Time-outs */
	timer_elt_data_t timer;		/* timer for thread */
	timer_elt_data_t depress_timer;	/* timer for priority depression */

	/* Ast/Halt data structures */
	/* Defined above */
	/* boolean_t	active;		   how alive is the thread */
	int		ast;    	/* ast's needed.  See ast.h */

	/* Processor data structures */
	processor_set_t	processor_set;	/* assigned processor set */
	processor_t	bound_processor;	/* bound to processor ?*/

	sample_control_t pc_sample;

#if	MACH_HOST
	boolean_t	may_assign;	/* may assignment change? */
	boolean_t	assign_active;	/* someone waiting for may_assign */
#endif	/* MACH_HOST */

#if	NCPUS > 1
	processor_t	last_processor; /* processor this last ran on */
#endif	/* NCPUS > 1 */
};

/* typedef of thread_t is in kern/kern_types.h */
typedef struct thread_shuttle	*thread_shuttle_t;
#define THREAD_NULL		((thread_t) 0)
#define THREAD_SHUTTLE_NULL	((thread_shuttle_t)0)

#define	ith_msize	data.msize
#define	ith_kmsg	data.kmsg
#define	ith_wait_result	wait_result

#define	ith_msg		saved.receive.msg
#define	ith_option	saved.receive.option
#define ith_rcv_size	saved.receive.rcv_size
#define ith_timeout	saved.receive.timeout
#define ith_notify	saved.receive.notify
#define ith_object	saved.receive.object
#define ith_mqueue	saved.receive.mqueue

#define	ith_port	saved.exception.port
#define ith_exc		saved.exception.exc
#define ith_exc_code	saved.exception.code
#define ith_exc_subcode	saved.exception.subcode

#define ith_other	saved.other

#ifndef	_KERN_KERN_TYPES_H_
typedef struct thread *thread_t;

#define THREAD_NULL	((thread_t) 0)

typedef	mach_port_t *thread_array_t;
#endif	/* _KERN_KERN_TYPES_H_ */


extern thread_t		active_threads[NCPUS];	/* active threads */
extern vm_offset_t	active_stacks[NCPUS];	/* active kernel stacks */

#ifdef KERNEL
/*
 *	User routines
 */

extern kern_return_t	thread_create(
	task_t		parent_task,
	thread_t	*child_thread);
extern kern_return_t	thread_terminate(
	thread_t	thread);
extern kern_return_t	thread_terminate_release(
	thread_t	thread,
	task_t		task,
	mach_port_t	thread_name,
	mach_port_t	reply_port,
	vm_offset_t	address,
	vm_size_t	size);
extern kern_return_t	thread_suspend(
	thread_t	thread);
extern kern_return_t	thread_resume(
	thread_t	thread);
extern kern_return_t	thread_abort(
	thread_t	thread);
extern void		thread_start(
	thread_t	thread,
	continuation_t	start);
extern thread_t		kernel_thread(
	task_t		task,
	continuation_t	start,
	void		*arg);
extern kern_return_t	thread_priority(
	thread_t	thread,
	int		priority,
	boolean_t	set_max);
extern void		thread_set_own_priority(
	int		priority);
extern kern_return_t	thread_max_priority(
	thread_t	thread,
	processor_set_t	pset,
	int		max_priority);
extern kern_return_t	thread_policy(
	thread_t	thread,
	int		policy,
	int		data);
extern void		consider_thread_collect(
	void);
extern void		stack_privilege(
	thread_t	thread);
extern kern_return_t	thread_get_state(
	thread_t	thread,
	int		flavor,
	thread_state_t	old_state,
	natural_t	*old_state_count);
extern kern_return_t	thread_set_state(
	thread_t	thread,
	int		flavor,
	thread_state_t	new_state,
	natural_t	new_state_count);
extern kern_return_t	thread_get_special_port(
	thread_t	thread,
	int		which,
	struct ipc_port	**portp);
extern kern_return_t	thread_set_special_port(
	thread_t	thread,
	int		which,
	struct ipc_port	*port);
extern kern_return_t	thread_info(
	thread_t	thread,
	int		flavor,
	thread_info_t	thread_info_out,
	natural_t	*thread_info_count);
extern kern_return_t	thread_assign(
	thread_t	thread,
	processor_set_t	new_pset);
extern kern_return_t	thread_assign_default(
	thread_t	thread);
extern void		stack_collect(void);
#endif

/*
 *	Kernel-only routines
 */

extern void		thread_init(void);
extern void		thread_reference(thread_t);
extern void		thread_deallocate(thread_t);
extern void		thread_hold(thread_t);
extern kern_return_t	thread_dowait(
	thread_t	thread,
	boolean_t	must_halt);
extern void		thread_release(thread_t);
extern kern_return_t	thread_halt(
	thread_t	thread,
	boolean_t	must_halt);
extern void		thread_halt_self(continuation_t);
extern void		thread_force_terminate(thread_t);
extern thread_t		kernel_thread(
	task_t		task,
	void		(*start)(void),
	void *		arg);

extern void		reaper_thread(void) __attribute__((noreturn));

#if	MACH_HOST
extern void		thread_freeze(
	thread_t	thread);
extern void		thread_doassign(
	thread_t	thread,
	processor_set_t	new_pset,
	boolean_t	release_freeze);
extern void		thread_unfreeze(
	thread_t	thread);
#endif	/* MACH_HOST */

/*
 *	Macro-defined routines
 */

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

#define thread_lock(th)		simple_lock(&(th)->lock)
#define thread_unlock(th)	simple_unlock(&(th)->lock)

#define thread_should_halt(thread)	\
		((thread)->ast & (AST_HALT|AST_TERMINATE))

/*
 *	Machine specific implementations of the current thread macro
 *	designate this by defining CURRENT_THREAD.
 */
#ifndef	CURRENT_THREAD
#define current_thread()	(active_threads[cpu_number()])
#endif	/* CURRENT_THREAD */

#define	current_stack()		(active_stacks[cpu_number()])

#define	current_task()		(current_thread()->task)
#define	current_space()		(current_task()->itk_space)
#define	current_map()		(current_task()->map)

#if MACH_DEBUG
void stack_init(vm_offset_t stack);
void stack_finalize(vm_offset_t stack);
#endif /* MACH_DEBUG */

#endif	/* _KERN_THREAD_H_ */