summaryrefslogtreecommitdiff
path: root/kern/processor.h
blob: b81526c0a9944857aeeb2be08c8bd9618ba1ab6c (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
/*
 * Mach Operating System
 * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
 * Copyright (c) 1993,1994 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.
 *
 * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
 * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM 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.
 */
/*
 *	processor.h:	Processor and processor-set definitions.
 */

#ifndef	_KERN_PROCESSOR_H_
#define	_KERN_PROCESSOR_H_

/*
 *	Data structures for managing processors and sets of processors.
 */

#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <mach/port.h>
#include <mach/processor_info.h>
#include <kern/cpu_number.h>
#include <kern/lock.h>
#include <kern/queue.h>
#include <kern/sched.h>
#include <kern/kern_types.h>
#include <kern/host.h>

#if	NCPUS > 1
#include <machine/ast_types.h>
#endif	/* NCPUS > 1 */

struct processor_set {
	struct run_queue	runq;		/* runq for this set */
	queue_head_t		idle_queue;	/* idle processors */
	int			idle_count;	/* how many ? */
	decl_simple_lock_data(,	idle_lock)	/* lock for above */
	queue_head_t		processors;	/* all processors here */
	int			processor_count;	/* how many ? */
	boolean_t		empty;		/* true if no processors */
	queue_head_t		tasks;		/* tasks assigned */
	int			task_count;	/* how many */
	queue_head_t		threads;	/* threads in this set */
	int			thread_count;	/* how many */
	int			ref_count;	/* structure ref count */
	decl_simple_lock_data(,	ref_lock)	/* lock for ref count */
	queue_chain_t		all_psets;	/* link for all_psets */
	boolean_t		active;		/* is pset in use */
	decl_simple_lock_data(,	lock)		/* lock for everything else */
	struct ipc_port	*	pset_self;	/* port for operations */
	struct ipc_port *	pset_name_self;	/* port for information */
	int			max_priority;	/* maximum priority */
#if	MACH_FIXPRI
	int			policies;	/* bit vector for policies */
#endif	/* MACH_FIXPRI */
	int			set_quantum;	/* current default quantum */
#if	NCPUS > 1
	int			quantum_adj_index; /* runtime quantum adj. */
	decl_simple_lock_data(,	quantum_adj_lock)  /* lock for above */
	int			machine_quantum[NCPUS+1]; /* ditto */
#endif	/* NCPUS > 1 */
	long			mach_factor;	/* mach_factor */
	long			load_average;	/* load_average */
	long			sched_load;	/* load avg for scheduler */
};
extern struct processor_set	default_pset;

struct processor {
	struct run_queue runq;		/* local runq for this processor */
		/* XXX want to do this round robin eventually */
	queue_chain_t	processor_queue; /* idle/assign/shutdown queue link */
	int		state;		/* See below */
	struct thread	*next_thread;	/* next thread to run if dispatched */
	struct thread	*idle_thread;	/* this processor's idle thread. */
	int		quantum;	/* quantum for current thread */
	boolean_t	first_quantum;	/* first quantum in succession */
	int		last_quantum;	/* last quantum assigned */

	processor_set_t	processor_set;	/* processor set I belong to */
	processor_set_t processor_set_next;	/* set I will belong to */
	queue_chain_t	processors;	/* all processors in set */
	decl_simple_lock_data(,	lock)
	struct ipc_port *processor_self;	/* port for operations */
	int		slot_num;	/* machine-indep slot number */
#if	NCPUS > 1
	ast_check_t	ast_check_data;	/* for remote ast_check invocation */
#endif	/* NCPUS > 1 */
	/* punt id data temporarily */
};
typedef struct processor Processor;
extern struct processor	processor_array[NCPUS];

/*
 *	Chain of all processor sets.
 */
extern queue_head_t		all_psets;
extern int			all_psets_count;
decl_simple_lock_data(extern, all_psets_lock);

/*
 *	The lock ordering is:
 *
 *			all_psets_lock
 *			    |
 *			    |
 *			    V
 *			pset_lock
 *			    |
 *		+-----------+---------------+-------------------+
 *		|	    |		    |			|
 *		|	    |		    |			|
 *		|	    |		    V			V
 *		|	    |		task_lock	pset_self->ip_lock
 *		|	    |		    |			|
 *		|	    |	+-----------+---------------+	|
 *		|	    |	|			    |	|
 *		|	    V	V			    V	V
 *		|	thread_lock*			pset_ref_lock
 *		|	    |
 *		|   +-------+
 *		|   |	    |
 *		|   |	    V
 *		|   |	runq_lock*
 *		|   |
 *		V   V
 *	processor_lock*
 *		|
 *		|
 *		V
 *	pset_idle_lock*
 *		|
 *		|
 *		V
 *	action_lock*
 *
 *	Locks marked with "*" are taken at splsched.
 */

/*
 *	XXX need a pointer to the master processor structure
 */

extern processor_t	master_processor;

/*
 *	NOTE: The processor->processor_set link is needed in one of the
 *	scheduler's critical paths.  [Figure out where to look for another
 *	thread to run on this processor.]  It is accessed without locking.
 *	The following access protocol controls this field.
 *
 *	Read from own processor - just read.
 *	Read from another processor - lock processor structure during read.
 *	Write from own processor - lock processor structure during write.
 *	Write from another processor - NOT PERMITTED.
 *
 */

/*
 *	Processor state locking:
 *
 *	Values for the processor state are defined below.  If the processor
 *	is off-line or being shutdown, then it is only necessary to lock
 *	the processor to change its state.  Otherwise it is only necessary
 *	to lock its processor set's idle_lock.  Scheduler code will
 *	typically lock only the idle_lock, but processor manipulation code
 *	will often lock both.
 */

#define PROCESSOR_OFF_LINE	0	/* Not in system */
#define	PROCESSOR_RUNNING	1	/* Running normally */
#define	PROCESSOR_IDLE		2	/* idle */
#define PROCESSOR_DISPATCHING	3	/* dispatching (idle -> running) */
#define	PROCESSOR_ASSIGN	4	/* Assignment is changing */
#define PROCESSOR_SHUTDOWN	5	/* Being shutdown */

/*
 *	Use processor ptr array to find current processor's data structure.
 *	This replaces a multiplication (index into processor_array) with
 *	an array lookup and a memory reference.  It also allows us to save
 *	space if processor numbering gets too sparse.
 */

extern processor_t	processor_ptr[NCPUS];

#define cpu_to_processor(i)	(processor_ptr[i])

#define current_processor()	(processor_ptr[cpu_number()])
#define current_processor_set()	(current_processor()->processor_set)

/* Compatibility -- will go away */

#define cpu_state(slot_num)	(processor_ptr[slot_num]->state)
#define cpu_idle(slot_num)	(cpu_state(slot_num) == PROCESSOR_IDLE)

/* Useful lock macros */

#define	pset_lock(pset)		simple_lock(&(pset)->lock)
#define pset_unlock(pset)	simple_unlock(&(pset)->lock)
#define	pset_ref_lock(pset)	simple_lock(&(pset)->ref_lock)
#define	pset_ref_unlock(pset)	simple_unlock(&(pset)->ref_lock)

#define processor_lock(pr)	simple_lock(&(pr)->lock)
#define processor_unlock(pr)	simple_unlock(&(pr)->lock)

typedef mach_port_t	*processor_array_t;
typedef mach_port_t	*processor_set_array_t;
typedef mach_port_t	*processor_set_name_array_t;


/*
 *	Exported functions
 */

/* Initialization */

#ifdef KERNEL
#if	MACH_HOST
extern void	pset_sys_init(void);
#endif	/* MACH_HOST */

/* Pset internal functions */

extern void	pset_sys_bootstrap(void);
extern void	pset_reference(processor_set_t);
extern void	pset_deallocate(processor_set_t);
extern void	pset_remove_processor(processor_set_t, processor_t);
extern void	pset_add_processor(processor_set_t, processor_t);
extern void	pset_remove_task(processor_set_t, struct task *);
extern void	pset_add_task(processor_set_t, struct task *);
extern void	pset_remove_thread(processor_set_t, struct thread *);
extern void	pset_add_thread(processor_set_t, struct thread *);
extern void	thread_change_psets(struct thread *,
				processor_set_t, processor_set_t);

/* Processor interface */

extern kern_return_t processor_get_assignment(
		processor_t	processor,
		processor_set_t *processor_set);

extern kern_return_t processor_info(
		processor_t	processor,
		int		flavor,
		host_t *	host,
		processor_info_t info,
		natural_t *	count);

extern kern_return_t processor_start(
		processor_t	processor);

extern kern_return_t processor_exit(
		processor_t	processor);

extern kern_return_t processor_control(
		processor_t	processor,
		processor_info_t info,
		natural_t 	count);

/* Pset interface */

extern kern_return_t processor_set_create(
		host_t		host,
		processor_set_t *new_set,
		processor_set_t *new_name);

extern kern_return_t processor_set_destroy(
		processor_set_t	pset);

extern kern_return_t processor_set_info(
		processor_set_t	pset,
		int		flavor,
		host_t		*host,
		processor_set_info_t info,
		natural_t	*count);

extern kern_return_t processor_set_max_priority(
		processor_set_t	pset,
		int		max_priority,
		boolean_t	change_threads);

extern kern_return_t processor_set_policy_enable(
		processor_set_t	pset,
		int		policy);

extern kern_return_t processor_set_policy_disable(
		processor_set_t	pset,
		int		policy,
		boolean_t	change_threads);

extern kern_return_t processor_set_tasks(
		processor_set_t	pset,
		task_array_t	*task_list,
		natural_t	*count);

extern kern_return_t processor_set_threads(
		processor_set_t	pset,
		thread_array_t	*thread_list,
		natural_t	*count);
#endif

void processor_doaction(processor_t processor);
void processor_doshutdown(processor_t processor);
void quantum_set(processor_set_t pset);
void pset_init(processor_set_t pset);
void processor_init(processor_t pr, int slot_num);

#endif	/* _KERN_PROCESSOR_H_ */