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_ */
|