FreeBSD/Linux Kernel Cross Reference
sys/kern/host.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,1991,1990,1989,1988 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: host.c,v $
29 * Revision 2.11 93/11/17 17:10:04 dbg
30 * Get min_quantum from kern/quantum.h.
31 * [93/05/11 dbg]
32 *
33 * Fixed host_info to correctly return min_timeout and min_quantum
34 * in milliseconds. Added ANSI function prototypes.
35 * [93/01/27 dbg]
36 *
37 * Revision 2.10 93/01/14 17:34:15 danner
38 * 64bit cleanup.
39 * [92/12/01 af]
40 *
41 * Revision 2.9 92/08/03 17:37:08 jfriedl
42 * removed silly prototypes
43 * [92/08/02 jfriedl]
44 *
45 * Revision 2.8 92/05/21 17:13:27 jfriedl
46 * Removed unused variable 'size_used' from host_processor_sets.
47 * Changes to quiet gcc warnings.
48 * [92/05/16 jfriedl]
49 *
50 * Revision 2.7 91/05/14 16:41:16 mrt
51 * Correcting copyright
52 *
53 * Revision 2.6 91/02/05 17:26:15 mrt
54 * Changed to new Mach copyright
55 * [91/02/01 16:12:16 mrt]
56 *
57 * Revision 2.5 90/08/27 22:02:30 dbg
58 * Fix bug in host_processor_sets. Import assert.h.
59 * [90/07/18 dbg]
60 *
61 * Revision 2.4 90/08/07 17:58:28 rpd
62 * Changed host_processor_sets to use unprivileged ports.
63 * [90/08/07 rpd]
64 *
65 * Revision 2.3 90/06/19 22:58:20 rpd
66 * Fixed bug in host_kernel_version.
67 * [90/06/16 rpd]
68 *
69 * Fixed bug in host_processors.
70 * [90/06/16 rpd]
71 *
72 * Revision 2.2 90/06/02 14:53:48 rpd
73 * Added HOST_LOAD_INFO.
74 * [90/04/27 rpd]
75 * Created for new host/processor technology.
76 * [90/03/26 23:50:27 rpd]
77 *
78 * Move includes.
79 * [89/08/02 dlb]
80 * Remove interrupt protection from all_psets lock.
81 * [89/06/14 dlb]
82 *
83 * Add host_processor_sets and host_processor_set_priv.
84 * [89/06/09 dlb]
85 *
86 * Add scheduler information flavor to host_info.
87 * [89/06/08 dlb]
88 * Declare realhost here.
89 * [89/02/03 dlb]
90 * [89/01/30 16:54:25 dlb]
91 *
92 * Revision 2.3 89/10/15 02:03:53 rpd
93 * Minor cleanups.
94 *
95 * Revision 2.2 89/10/11 14:04:44 dlb
96 * Optimize host_processor_sets and add simplified !MACH_HOST case.
97 * Remove interrupt protection from all_psets lock.
98 * Add host_processor_sets and host_processor_set_priv.
99 * Add scheduler information flavor to host_info.
100 *
101 * Reformat includes. mach_host.h moved to mach/ directory.
102 * [89/01/26 dlb]
103 *
104 * Move kernel version to a separate routine so it can be returned
105 * as a string of characters.
106 * [88/12/02 dlb]
107 *
108 * Bug fixes, add new flavors of host information.
109 * [88/12/01 dlb]
110 *
111 * Created.
112 * [88/10/31 dlb]
113 */
114
115 /*
116 * host.c
117 *
118 * Non-ipc host functions.
119 */
120
121 #include <cpus.h>
122 #include <mach_host.h>
123
124 #include <kern/assert.h>
125 #include <kern/kalloc.h>
126 #include <kern/host.h>
127 #include <mach/host_info.h>
128 #include <mach/kern_return.h>
129 #include <mach/machine.h>
130 #include <mach/port.h>
131 #include <kern/machine.h>
132 #include <kern/memory.h>
133 #include <kern/processor.h>
134 #include <kern/quantum.h>
135 #include <kern/strings.h>
136 #include <kern/ipc_host.h>
137
138 #include <mach/vm_param.h>
139
140
141
142 host_data_t realhost;
143
144 kern_return_t host_processors(
145 host_t host,
146 processor_array_t *processor_list,
147 natural_t *countp)
148 {
149 register int i;
150 register processor_t *tp;
151 vm_offset_t addr;
152 unsigned int count;
153
154 if (host == HOST_NULL)
155 return KERN_INVALID_ARGUMENT;
156
157 /*
158 * Determine how many processors we have.
159 * (This number shouldn't change.)
160 */
161
162 count = 0;
163 for (i = 0; i < NCPUS; i++)
164 if (machine_slot[i].is_cpu)
165 count++;
166
167 if (count == 0)
168 panic("host_processors");
169
170 addr = kalloc((vm_size_t) (count * sizeof(mach_port_t)));
171 if (addr == 0)
172 return KERN_RESOURCE_SHORTAGE;
173
174 tp = (processor_t *) addr;
175 for (i = 0; i < NCPUS; i++)
176 if (machine_slot[i].is_cpu)
177 *tp++ = cpu_to_processor(i);
178
179 *countp = count;
180 *processor_list = (mach_port_t *) addr;
181
182 /* do the conversion that Mig should handle */
183
184 tp = (processor_t *) addr;
185 for (i = 0; i < count; i++)
186 ((mach_port_t *) tp)[i] =
187 (mach_port_t)convert_processor_to_port(tp[i]);
188
189 return KERN_SUCCESS;
190 }
191
192 kern_return_t host_info(
193 host_t host,
194 int flavor,
195 host_info_t info,
196 natural_t *count)
197 {
198 register integer_t i, *slot_ptr;
199
200 if (host == HOST_NULL)
201 return KERN_INVALID_ARGUMENT;
202
203 switch(flavor) {
204
205 case HOST_BASIC_INFO:
206 {
207 register host_basic_info_t basic_info;
208
209 /*
210 * Basic information about this host.
211 */
212 if (*count < HOST_BASIC_INFO_COUNT)
213 return KERN_FAILURE;
214
215 basic_info = (host_basic_info_t) info;
216
217 basic_info->max_cpus = machine_info.max_cpus;
218 basic_info->avail_cpus = machine_info.avail_cpus;
219 basic_info->memory_size = machine_info.memory_size;
220 basic_info->cpu_type =
221 machine_slot[master_processor->slot_num].cpu_type;
222 basic_info->cpu_subtype =
223 machine_slot[master_processor->slot_num].cpu_subtype;
224
225 *count = HOST_BASIC_INFO_COUNT;
226 return KERN_SUCCESS;
227 }
228
229 case HOST_PROCESSOR_SLOTS:
230 /*
231 * Return numbers of slots with active processors
232 * in them.
233 */
234 if (*count < NCPUS)
235 return KERN_INVALID_ARGUMENT;
236
237 slot_ptr = (integer_t *)info;
238 *count = 0;
239 for (i = 0; i < NCPUS; i++) {
240 if (machine_slot[i].is_cpu &&
241 machine_slot[i].running) {
242 *slot_ptr++ = i;
243 (*count)++;
244 }
245 }
246 return KERN_SUCCESS;
247
248 case HOST_SCHED_INFO:
249 {
250 register host_sched_info_t sched_info;
251
252 /*
253 * Return scheduler information.
254 */
255 if (*count < HOST_SCHED_INFO_COUNT)
256 return KERN_FAILURE;
257
258 sched_info = (host_sched_info_t) info;
259
260 sched_info->min_timeout = 10; /* XXX */
261 sched_info->min_quantum = min_quantum / 1000;
262 /* convert microseconds to milliseconds */
263
264 *count = HOST_SCHED_INFO_COUNT;
265 return KERN_SUCCESS;
266 }
267
268 case HOST_LOAD_INFO:
269 {
270 register host_load_info_t load_info;
271 extern long avenrun[3], mach_factor[3];
272
273 if (*count < HOST_LOAD_INFO_COUNT)
274 return KERN_FAILURE;
275
276 load_info = (host_load_info_t) info;
277
278 bcopy(avenrun,
279 load_info->avenrun,
280 sizeof avenrun);
281 bcopy(mach_factor,
282 load_info->mach_factor,
283 sizeof mach_factor);
284
285 *count = HOST_LOAD_INFO_COUNT;
286 return KERN_SUCCESS;
287 }
288
289 default:
290 return KERN_INVALID_ARGUMENT;
291 }
292 }
293
294 /*
295 * Return kernel version string (more than you ever
296 * wanted to know about what version of the kernel this is).
297 */
298
299 kern_return_t host_kernel_version(
300 host_t host,
301 kernel_version_t out_version)
302 {
303 extern char version[];
304
305 if (host == HOST_NULL)
306 return KERN_INVALID_ARGUMENT;
307
308 (void) strncpy(out_version, version, sizeof(kernel_version_t));
309
310 return KERN_SUCCESS;
311 }
312
313 /*
314 * host_processor_sets:
315 *
316 * List all processor sets on the host.
317 */
318 #if MACH_HOST
319 kern_return_t
320 host_processor_sets(
321 host_t host,
322 processor_set_name_array_t *pset_list,
323 natural_t *count)
324 {
325 unsigned int actual; /* this many psets */
326 processor_set_t pset;
327 processor_set_t *psets;
328 int i;
329
330 vm_size_t size;
331 vm_size_t size_needed;
332 vm_offset_t addr;
333
334 if (host == HOST_NULL)
335 return KERN_INVALID_ARGUMENT;
336
337 size = 0; addr = 0;
338
339 for (;;) {
340 simple_lock(&all_psets_lock);
341 actual = all_psets_count;
342
343 /* do we have the memory we need? */
344
345 size_needed = actual * sizeof(mach_port_t);
346 if (size_needed <= size)
347 break;
348
349 /* unlock and allocate more memory */
350 simple_unlock(&all_psets_lock);
351
352 if (size != 0)
353 kfree(addr, size);
354
355 assert(size_needed > 0);
356 size = size_needed;
357
358 addr = kalloc(size);
359 if (addr == 0)
360 return KERN_RESOURCE_SHORTAGE;
361 }
362
363 /* OK, have memory and the all_psets_lock */
364
365 psets = (processor_set_t *) addr;
366
367 for (i = 0, pset = (processor_set_t) queue_first(&all_psets);
368 i < actual;
369 i++, pset = (processor_set_t) queue_next(&pset->all_psets)) {
370 /* take ref for convert_pset_name_to_port */
371 pset_reference(pset);
372 psets[i] = pset;
373 }
374 assert(queue_end(&all_psets, (queue_entry_t) pset));
375
376 /* can unlock now that we've got the pset refs */
377 simple_unlock(&all_psets_lock);
378
379 /*
380 * Always have default port.
381 */
382
383 assert(actual > 0);
384
385 /* if we allocated too much, must copy */
386
387 if (size_needed < size) {
388 vm_offset_t newaddr;
389
390 newaddr = kalloc(size_needed);
391 if (newaddr == 0) {
392 for (i = 0; i < actual; i++)
393 pset_deallocate(psets[i]);
394 kfree(addr, size);
395 return KERN_RESOURCE_SHORTAGE;
396 }
397
398 bcopy((void *) addr, (void *) newaddr, size_needed);
399 kfree(addr, size);
400 psets = (processor_set_t *) newaddr;
401 }
402
403 *pset_list = (mach_port_t *) psets;
404 *count = actual;
405
406 /* do the conversion that Mig should handle */
407
408 for (i = 0; i < actual; i++)
409 ((mach_port_t *) psets)[i] =
410 (mach_port_t)convert_pset_name_to_port(psets[i]);
411
412 return KERN_SUCCESS;
413 }
414 #else /* MACH_HOST */
415 /*
416 * Only one processor set, the default processor set, in this case.
417 */
418 kern_return_t
419 host_processor_sets(
420 host_t host,
421 processor_set_name_array_t *pset_list,
422 natural_t *count)
423 {
424 vm_offset_t addr;
425
426 if (host == HOST_NULL)
427 return KERN_INVALID_ARGUMENT;
428
429 /*
430 * Allocate memory. Can be pageable because it won't be
431 * touched while holding a lock.
432 */
433
434 addr = kalloc((vm_size_t) sizeof(mach_port_t));
435 if (addr == 0)
436 return KERN_RESOURCE_SHORTAGE;
437
438 /* take for for convert_pset_name_to_port */
439 pset_reference(&default_pset);
440 /* do the conversion that Mig should handle */
441 *((mach_port_t *) addr) =
442 (mach_port_t) convert_pset_name_to_port(&default_pset);
443
444 *pset_list = (mach_port_t *) addr;
445 *count = 1;
446
447 return KERN_SUCCESS;
448 }
449 #endif /* MACH_HOST */
450
451 /*
452 * host_processor_set_priv:
453 *
454 * Return control port for given processor set.
455 */
456 kern_return_t
457 host_processor_set_priv(
458 host_t host,
459 processor_set_t pset_name,
460 processor_set_t *pset)
461 {
462 if ((host == HOST_NULL) || (pset_name == PROCESSOR_SET_NULL)) {
463 *pset = PROCESSOR_SET_NULL;
464 return KERN_INVALID_ARGUMENT;
465 }
466
467 *pset = pset_name;
468 pset_reference(*pset);
469 return KERN_SUCCESS;
470 }
Cache object: cdf4bff12a64cdc3af0e29002cce4df3
|