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