|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1993-1988 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50:
51: /*
52: * processor.c: processor and processor_set manipulation routines.
53: */
54:
55: #include <cpus.h>
56: #include <mach_fixpri.h>
57: #include <mach_host.h>
58:
59: #include <mach/boolean.h>
60: #include <mach/policy.h>
61: #include <mach/processor_info.h>
62: #include <mach/vm_param.h>
63: #include <kern/cpu_number.h>
64: #include <kern/lock.h>
65: #include <kern/host.h>
66: #include <kern/processor.h>
67: #include <kern/sched.h>
68: #include <kern/task.h>
69: #include <kern/thread.h>
70: #include <kern/ipc_host.h>
71: #include <ipc/ipc_port.h>
72:
73: #if MACH_HOST
74: #include <kern/zalloc.h>
75: zone_t pset_zone;
76: #endif /* MACH_HOST */
77:
78:
79: /*
80: * Exported variables.
81: */
82: struct processor_set default_pset;
83: struct processor processor_array[NCPUS];
84:
85: queue_head_t all_psets;
86: int all_psets_count;
87: decl_simple_lock_data(, all_psets_lock);
88:
89: processor_t master_processor;
90: processor_t processor_ptr[NCPUS];
91:
92: /*
93: * Forward declarations.
94: */
95: void quantum_set(processor_set_t);
96: void pset_init(processor_set_t);
97: void processor_init(processor_t, int);
98:
99: /*
100: * Bootstrap the processor/pset system so the scheduler can run.
101: */
102: void pset_sys_bootstrap(void)
103: {
104: register int i;
105:
106: pset_init(&default_pset);
107: default_pset.empty = FALSE;
108: for (i = 0; i < NCPUS; i++) {
109: /*
110: * Initialize processor data structures.
111: * Note that cpu_to_processor(i) is processor_ptr[i].
112: */
113: processor_ptr[i] = &processor_array[i];
114: processor_init(processor_ptr[i], i);
115: }
116: master_processor = cpu_to_processor(master_cpu);
117: queue_init(&all_psets);
118: simple_lock_init(&all_psets_lock);
119: queue_enter(&all_psets, &default_pset, processor_set_t, all_psets);
120: all_psets_count = 1;
121: default_pset.active = TRUE;
122: default_pset.empty = FALSE;
123:
124: /*
125: * Note: the default_pset has a max_priority of MAXPRI_USER.
126: * Internal kernel threads override this in kernel_thread.
127: */
128: }
129:
130: #if MACH_HOST
131: /*
132: * Rest of pset system initializations.
133: */
134: void pset_sys_init(void)
135: {
136: register int i;
137: register processor_t processor;
138:
139: /*
140: * Allocate the zone for processor sets.
141: */
142: pset_zone = zinit(sizeof(struct processor_set), 128*PAGE_SIZE,
143: PAGE_SIZE, FALSE, "processor sets");
144:
145: /*
146: * Give each processor a control port.
147: * The master processor already has one.
148: */
149: for (i = 0; i < NCPUS; i++) {
150: processor = cpu_to_processor(i);
151: if (processor != master_processor &&
152: machine_slot[i].is_cpu)
153: {
154: ipc_processor_init(processor);
155: }
156: }
157: }
158: #endif /* MACH_HOST */
159:
160: /*
161: * Initialize the given processor_set structure.
162: */
163:
164: void pset_init(
165: register processor_set_t pset)
166: {
167: int i;
168:
169: simple_lock_init(&pset->runq.lock);
170: pset->runq.high = NRQS-1;
171: pset->runq.count = 0;
172: for (i = 0; i < NRQS; i++) {
173: queue_init(&(pset->runq.runq[i]));
174: }
175: queue_init(&pset->idle_queue);
176: pset->idle_count = 0;
177: simple_lock_init(&pset->idle_lock);
178: queue_init(&pset->processors);
179: pset->processor_count = 0;
180: pset->empty = TRUE;
181: queue_init(&pset->tasks);
182: pset->task_count = 0;
183: queue_init(&pset->threads);
184: pset->thread_count = 0;
185: pset->ref_count = 1;
186: simple_lock_init(&pset->ref_lock);
187: queue_init(&pset->all_psets);
188: pset->active = FALSE;
189: simple_lock_init(&pset->lock);
190: pset->pset_self = IP_NULL;
191: pset->pset_name_self = IP_NULL;
192: pset->max_priority = MAXPRI_USER;
193: #if MACH_FIXPRI
194: pset->policies = POLICY_TIMESHARE;
195: #endif /* MACH_FIXPRI */
196: pset->set_quantum = min_quantum;
197: #if NCPUS > 1
198: pset->quantum_adj_index = 0;
199: simple_lock_init(&pset->quantum_adj_lock);
200:
201: for (i = 0; i <= NCPUS; i++) {
202: pset->machine_quantum[i] = min_quantum;
203: }
204: #endif /* NCPUS > 1 */
205: pset->mach_factor = 0;
206: pset->load_average = 0;
207: pset->sched_load = SCHED_SCALE; /* i.e. 1 */
208: }
209:
210: /*
211: * Initialize the given processor structure for the processor in
212: * the slot specified by slot_num.
213: */
214:
215: void processor_init(
216: register processor_t pr,
217: int slot_num)
218: {
219: int i;
220:
221: simple_lock_init(&pr->runq.lock);
222: pr->runq.high = NRQS-1;
223: pr->runq.count = 0;
224: for (i = 0; i < NRQS; i++) {
225: queue_init(&(pr->runq.runq[i]));
226: }
227: queue_init(&pr->processor_queue);
228: pr->state = PROCESSOR_OFF_LINE;
229: pr->next_thread = THREAD_NULL;
230: pr->idle_thread = THREAD_NULL;
231: pr->quantum = 0;
232: pr->first_quantum = FALSE;
233: pr->last_quantum = 0;
234: pr->processor_set = PROCESSOR_SET_NULL;
235: pr->processor_set_next = PROCESSOR_SET_NULL;
236: queue_init(&pr->processors);
237: simple_lock_init(&pr->lock);
238: pr->processor_self = IP_NULL;
239: pr->slot_num = slot_num;
240: }
241:
242: /*
243: * pset_remove_processor() removes a processor from a processor_set.
244: * It can only be called on the current processor. Caller must
245: * hold lock on current processor and processor set.
246: */
247:
248: void pset_remove_processor(
249: processor_set_t pset,
250: processor_t processor)
251: {
252: if (pset != processor->processor_set)
253: panic("pset_remove_processor: wrong pset");
254:
255: queue_remove(&pset->processors, processor, processor_t, processors);
256: processor->processor_set = PROCESSOR_SET_NULL;
257: pset->processor_count--;
258: quantum_set(pset);
259: }
260:
261: /*
262: * pset_add_processor() adds a processor to a processor_set.
263: * It can only be called on the current processor. Caller must
264: * hold lock on curent processor and on pset. No reference counting on
265: * processors. Processor reference to pset is implicit.
266: */
267:
268: void pset_add_processor(
269: processor_set_t pset,
270: processor_t processor)
271: {
272: queue_enter(&pset->processors, processor, processor_t, processors);
273: processor->processor_set = pset;
274: pset->processor_count++;
275: quantum_set(pset);
276: }
277:
278: /*
279: * pset_remove_task() removes a task from a processor_set.
280: * Caller must hold locks on pset and task. Pset reference count
281: * is not decremented; caller must explicitly pset_deallocate.
282: */
283:
284: void pset_remove_task(
285: processor_set_t pset,
286: task_t task)
287: {
288: if (pset != task->processor_set)
289: return;
290:
291: queue_remove(&pset->tasks, task, task_t, pset_tasks);
292: task->processor_set = PROCESSOR_SET_NULL;
293: pset->task_count--;
294: }
295:
296: /*
297: * pset_add_task() adds a task to a processor_set.
298: * Caller must hold locks on pset and task. Pset references to
299: * tasks are implicit.
300: */
301:
302: void pset_add_task(
303: processor_set_t pset,
304: task_t task)
305: {
306: queue_enter(&pset->tasks, task, task_t, pset_tasks);
307: task->processor_set = pset;
308: pset->task_count++;
309: }
310:
311: /*
312: * pset_remove_thread() removes a thread from a processor_set.
313: * Caller must hold locks on pset and thread. Pset reference count
314: * is not decremented; caller must explicitly pset_deallocate.
315: */
316:
317: void pset_remove_thread(
318: processor_set_t pset,
319: thread_t thread)
320: {
321: queue_remove(&pset->threads, thread, thread_t, pset_threads);
322: thread->processor_set = PROCESSOR_SET_NULL;
323: pset->thread_count--;
324: }
325:
326: /*
327: * pset_add_thread() adds a thread to a processor_set.
328: * Caller must hold locks on pset and thread. Pset references to
329: * threads are implicit.
330: */
331:
332: void pset_add_thread(
333: processor_set_t pset,
334: thread_t thread)
335: {
336: queue_enter(&pset->threads, thread, thread_t, pset_threads);
337: thread->processor_set = pset;
338: pset->thread_count++;
339: }
340:
341: /*
342: * thread_change_psets() changes the pset of a thread. Caller must
343: * hold locks on both psets and thread. The old pset must be
344: * explicitly pset_deallocat()'ed by caller.
345: */
346:
347: void thread_change_psets(
348: thread_t thread,
349: processor_set_t old_pset,
350: processor_set_t new_pset)
351: {
352: queue_remove(&old_pset->threads, thread, thread_t, pset_threads);
353: old_pset->thread_count--;
354: queue_enter(&new_pset->threads, thread, thread_t, pset_threads);
355: thread->processor_set = new_pset;
356: new_pset->thread_count++;
357: }
358:
359: /*
360: * pset_deallocate:
361: *
362: * Remove one reference to the processor set. Destroy processor_set
363: * if this was the last reference.
364: */
365: void pset_deallocate(
366: processor_set_t pset)
367: {
368: if (pset == PROCESSOR_SET_NULL)
369: return;
370:
371: pset_ref_lock(pset);
372: if (--pset->ref_count > 0) {
373: pset_ref_unlock(pset);
374: return;
375: }
376: #if !MACH_HOST
377: panic("pset_deallocate: default_pset destroyed");
378: #endif /* !MACH_HOST */
379:
380: #if MACH_HOST
381: /*
382: * Reference count is zero, however the all_psets list
383: * holds an implicit reference and may make new ones.
384: * Its lock also dominates the pset lock. To check for this,
385: * temporarily restore one reference, and then lock the
386: * other structures in the right order.
387: */
388: pset->ref_count = 1;
389: pset_ref_unlock(pset);
390:
391: simple_lock(&all_psets_lock);
392: pset_ref_lock(pset);
393: if (--pset->ref_count > 0) {
394: /*
395: * Made an extra reference.
396: */
397: pset_ref_unlock(pset);
398: simple_unlock(&all_psets_lock);
399: return;
400: }
401:
402: /*
403: * Ok to destroy pset. Make a few paranoia checks.
404: */
405:
406: if ((pset == &default_pset) || (pset->thread_count > 0) ||
407: (pset->task_count > 0) || pset->processor_count > 0) {
408: panic("pset_deallocate: destroy default or active pset");
409: }
410: /*
411: * Remove from all_psets queue.
412: */
413: queue_remove(&all_psets, pset, processor_set_t, all_psets);
414: all_psets_count--;
415:
416: pset_ref_unlock(pset);
417: simple_unlock(&all_psets_lock);
418:
419: /*
420: * That's it, free data structure.
421: */
422: zfree(pset_zone, (vm_offset_t)pset);
423: #endif /* MACH_HOST */
424: }
425:
426: /*
427: * pset_reference:
428: *
429: * Add one reference to the processor set.
430: */
431: void pset_reference(
432: processor_set_t pset)
433: {
434: pset_ref_lock(pset);
435: pset->ref_count++;
436: pset_ref_unlock(pset);
437: }
438:
439: kern_return_t
440: processor_info(
441: register processor_t processor,
442: int flavor,
443: host_t *host,
444: processor_info_t info,
445: natural_t *count)
446: {
447: register int slot_num, state;
448: register processor_basic_info_t basic_info;
449:
450: if (processor == PROCESSOR_NULL)
451: return KERN_INVALID_ARGUMENT;
452:
453: if (flavor != PROCESSOR_BASIC_INFO ||
454: *count < PROCESSOR_BASIC_INFO_COUNT)
455: return KERN_FAILURE;
456:
457: basic_info = (processor_basic_info_t) info;
458:
459: slot_num = processor->slot_num;
460: basic_info->cpu_type = machine_slot[slot_num].cpu_type;
461: basic_info->cpu_subtype = machine_slot[slot_num].cpu_subtype;
462: state = processor->state;
463: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE)
464: basic_info->running = FALSE;
465: else
466: basic_info->running = TRUE;
467: basic_info->slot_num = slot_num;
468: if (processor == master_processor)
469: basic_info->is_master = TRUE;
470: else
471: basic_info->is_master = FALSE;
472:
473: *count = PROCESSOR_BASIC_INFO_COUNT;
474: *host = &realhost;
475: return KERN_SUCCESS;
476: }
477:
478: kern_return_t processor_start(
479: processor_t processor)
480: {
481: if (processor == PROCESSOR_NULL)
482: return KERN_INVALID_ARGUMENT;
483: #if NCPUS > 1
484: return cpu_start(processor->slot_num);
485: #else /* NCPUS > 1 */
486: return KERN_FAILURE;
487: #endif /* NCPUS > 1 */
488: }
489:
490: kern_return_t processor_exit(
491: processor_t processor)
492: {
493: if (processor == PROCESSOR_NULL)
494: return KERN_INVALID_ARGUMENT;
495:
496: #if NCPUS > 1
497: return processor_shutdown(processor);
498: #else /* NCPUS > 1 */
499: return KERN_FAILURE;
500: #endif /* NCPUS > 1 */
501: }
502:
503: kern_return_t
504: processor_control(
505: processor_t processor,
506: processor_info_t info,
507: natural_t count)
508: {
509: if (processor == PROCESSOR_NULL)
510: return KERN_INVALID_ARGUMENT;
511:
512: #if NCPUS > 1
513: return cpu_control(processor->slot_num, (int *)info, count);
514: #else /* NCPUS > 1 */
515: return KERN_FAILURE;
516: #endif /* NCPUS > 1 */
517: }
518:
519: /*
520: * Precalculate the appropriate system quanta based on load. The
521: * index into machine_quantum is the number of threads on the
522: * processor set queue. It is limited to the number of processors in
523: * the set.
524: */
525:
526: void quantum_set(
527: processor_set_t pset)
528: {
529: #if NCPUS > 1
530: register int i,ncpus;
531:
532: ncpus = pset->processor_count;
533:
534: for ( i=1 ; i <= ncpus ; i++) {
535: pset->machine_quantum[i] =
536: ((min_quantum * ncpus) + (i/2)) / i ;
537: }
538: pset->machine_quantum[0] = 2 * pset->machine_quantum[1];
539:
540: i = ((pset->runq.count > pset->processor_count) ?
541: pset->processor_count : pset->runq.count);
542: pset->set_quantum = pset->machine_quantum[i];
543: #else /* NCPUS > 1 */
544: default_pset.set_quantum = min_quantum;
545: #endif /* NCPUS > 1 */
546: }
547:
548: #if MACH_HOST
549: /*
550: * processor_set_create:
551: *
552: * Create and return a new processor set.
553: */
554:
555: kern_return_t
556: processor_set_create(
557: host_t host,
558: processor_set_t *new_set,
559: processor_set_t *new_name)
560: {
561: processor_set_t pset;
562:
563: if (host == HOST_NULL)
564: return KERN_INVALID_ARGUMENT;
565:
566: pset = (processor_set_t) zalloc(pset_zone);
567: pset_init(pset);
568: pset_reference(pset); /* for new_set out argument */
569: pset_reference(pset); /* for new_name out argument */
570: ipc_pset_init(pset);
571: pset->active = TRUE;
572:
573: simple_lock(&all_psets_lock);
574: queue_enter(&all_psets, pset, processor_set_t, all_psets);
575: all_psets_count++;
576: simple_unlock(&all_psets_lock);
577:
578: ipc_pset_enable(pset);
579:
580: *new_set = pset;
581: *new_name = pset;
582: return KERN_SUCCESS;
583: }
584:
585: /*
586: * processor_set_destroy:
587: *
588: * destroy a processor set. Any tasks, threads or processors
589: * currently assigned to it are reassigned to the default pset.
590: */
591: kern_return_t processor_set_destroy(
592: processor_set_t pset)
593: {
594: register queue_entry_t elem;
595: register queue_head_t *list;
596:
597: if (pset == PROCESSOR_SET_NULL || pset == &default_pset)
598: return KERN_INVALID_ARGUMENT;
599:
600: /*
601: * Handle multiple termination race. First one through sets
602: * active to FALSE and disables ipc access.
603: */
604: pset_lock(pset);
605: if (!(pset->active)) {
606: pset_unlock(pset);
607: return KERN_FAILURE;
608: }
609:
610: pset->active = FALSE;
611: ipc_pset_disable(pset);
612:
613:
614: /*
615: * Now reassign everything in this set to the default set.
616: */
617:
618: if (pset->task_count > 0) {
619: list = &pset->tasks;
620: while (!queue_empty(list)) {
621: elem = queue_first(list);
622: task_reference((task_t) elem);
623: pset_unlock(pset);
624: task_assign((task_t) elem, &default_pset, FALSE);
625: task_deallocate((task_t) elem);
626: pset_lock(pset);
627: }
628: }
629:
630: if (pset->thread_count > 0) {
631: list = &pset->threads;
632: while (!queue_empty(list)) {
633: elem = queue_first(list);
634: thread_reference((thread_t) elem);
635: pset_unlock(pset);
636: thread_assign((thread_t) elem, &default_pset);
637: thread_deallocate((thread_t) elem);
638: pset_lock(pset);
639: }
640: }
641:
642: if (pset->processor_count > 0) {
643: list = &pset->processors;
644: while(!queue_empty(list)) {
645: elem = queue_first(list);
646: pset_unlock(pset);
647: processor_assign((processor_t) elem, &default_pset, TRUE);
648: pset_lock(pset);
649: }
650: }
651:
652: pset_unlock(pset);
653:
654: /*
655: * Destroy ipc state.
656: */
657: ipc_pset_terminate(pset);
658:
659: /*
660: * Deallocate pset's reference to itself.
661: */
662: pset_deallocate(pset);
663: return KERN_SUCCESS;
664: }
665:
666: #else /* MACH_HOST */
667:
668: kern_return_t
669: processor_set_create(
670: host_t host,
671: processor_set_t *new_set,
672: processor_set_t *new_name)
673: {
674: #ifdef lint
675: host++; new_set++; new_name++;
676: #endif /* lint */
677: return KERN_FAILURE;
678: }
679:
680: kern_return_t processor_set_destroy(
681: processor_set_t pset)
682: {
683: #ifdef lint
684: pset++;
685: #endif /* lint */
686: return KERN_FAILURE;
687: }
688:
689: #endif MACH_HOST
690:
691: kern_return_t
692: processor_get_assignment(
693: processor_t processor,
694: processor_set_t *pset)
695: {
696: int state;
697:
698: state = processor->state;
699: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE)
700: return KERN_FAILURE;
701:
702: *pset = processor->processor_set;
703: pset_reference(*pset);
704: return KERN_SUCCESS;
705: }
706:
707: kern_return_t
708: processor_set_info(
709: processor_set_t pset,
710: int flavor,
711: host_t *host,
712: processor_set_info_t info,
713: natural_t *count)
714: {
715: if (pset == PROCESSOR_SET_NULL)
716: return KERN_INVALID_ARGUMENT;
717:
718: if (flavor == PROCESSOR_SET_BASIC_INFO) {
719: register processor_set_basic_info_t basic_info;
720:
721: if (*count < PROCESSOR_SET_BASIC_INFO_COUNT)
722: return KERN_FAILURE;
723:
724: basic_info = (processor_set_basic_info_t) info;
725:
726: pset_lock(pset);
727: basic_info->processor_count = pset->processor_count;
728: basic_info->task_count = pset->task_count;
729: basic_info->thread_count = pset->thread_count;
730: basic_info->mach_factor = pset->mach_factor;
731: basic_info->load_average = pset->load_average;
732: pset_unlock(pset);
733:
734: *count = PROCESSOR_SET_BASIC_INFO_COUNT;
735: *host = &realhost;
736: return KERN_SUCCESS;
737: }
738: else if (flavor == PROCESSOR_SET_SCHED_INFO) {
739: register processor_set_sched_info_t sched_info;
740:
741: if (*count < PROCESSOR_SET_SCHED_INFO_COUNT)
742: return KERN_FAILURE;
743:
744: sched_info = (processor_set_sched_info_t) info;
745:
746: pset_lock(pset);
747: #if MACH_FIXPRI
748: sched_info->policies = pset->policies;
749: #else /* MACH_FIXPRI */
750: sched_info->policies = POLICY_TIMESHARE;
751: #endif /* MACH_FIXPRI */
752: sched_info->max_priority = pset->max_priority;
753: pset_unlock(pset);
754:
755: *count = PROCESSOR_SET_SCHED_INFO_COUNT;
756: *host = &realhost;
757: return KERN_SUCCESS;
758: }
759:
760: *host = HOST_NULL;
761: return KERN_INVALID_ARGUMENT;
762: }
763:
764: /*
765: * processor_set_max_priority:
766: *
767: * Specify max priority permitted on processor set. This affects
768: * newly created and assigned threads. Optionally change existing
769: * ones.
770: */
771: kern_return_t
772: processor_set_max_priority(
773: processor_set_t pset,
774: int max_priority,
775: boolean_t change_threads)
776: {
777: if (pset == PROCESSOR_SET_NULL || invalid_pri(max_priority))
778: return KERN_INVALID_ARGUMENT;
779:
780: pset_lock(pset);
781: pset->max_priority = max_priority;
782:
783: if (change_threads) {
784: register queue_head_t *list;
785: register thread_t thread;
786:
787: list = &pset->threads;
788: queue_iterate(list, thread, thread_t, pset_threads) {
789: if (thread->max_priority < max_priority)
790: thread_max_priority(thread, pset, max_priority);
791: }
792: }
793:
794: pset_unlock(pset);
795:
796: return KERN_SUCCESS;
797: }
798:
799: /*
800: * processor_set_policy_enable:
801: *
802: * Allow indicated policy on processor set.
803: */
804:
805: kern_return_t
806: processor_set_policy_enable(
807: processor_set_t pset,
808: int policy)
809: {
810: if ((pset == PROCESSOR_SET_NULL) || invalid_policy(policy))
811: return KERN_INVALID_ARGUMENT;
812:
813: #if MACH_FIXPRI
814: pset_lock(pset);
815: pset->policies |= policy;
816: pset_unlock(pset);
817:
818: return KERN_SUCCESS;
819: #else /* MACH_FIXPRI */
820: if (policy == POLICY_TIMESHARE)
821: return KERN_SUCCESS;
822: else
823: return KERN_FAILURE;
824: #endif /* MACH_FIXPRI */
825: }
826:
827: /*
828: * processor_set_policy_disable:
829: *
830: * Forbid indicated policy on processor set. Time sharing cannot
831: * be forbidden.
832: */
833:
834: kern_return_t
835: processor_set_policy_disable(
836: processor_set_t pset,
837: int policy,
838: boolean_t change_threads)
839: {
840: if ((pset == PROCESSOR_SET_NULL) || policy == POLICY_TIMESHARE ||
841: invalid_policy(policy))
842: return KERN_INVALID_ARGUMENT;
843:
844: #if MACH_FIXPRI
845: pset_lock(pset);
846:
847: /*
848: * Check if policy enabled. Disable if so, then handle
849: * change_threads.
850: */
851: if (pset->policies & policy) {
852: pset->policies &= ~policy;
853:
854: if (change_threads) {
855: register queue_head_t *list;
856: register thread_t thread;
857:
858: list = &pset->threads;
859: queue_iterate(list, thread, thread_t, pset_threads) {
860: if (thread->policy == policy)
861: thread_policy(thread, POLICY_TIMESHARE, 0);
862: }
863: }
864: }
865: pset_unlock(pset);
866: #endif /* MACH_FIXPRI */
867:
868: return KERN_SUCCESS;
869: }
870:
871: #define THING_TASK 0
872: #define THING_THREAD 1
873:
874: /*
875: * processor_set_things:
876: *
877: * Common internals for processor_set_{threads,tasks}
878: */
879: kern_return_t
880: processor_set_things(
881: processor_set_t pset,
882: mach_port_t **thing_list,
883: natural_t *count,
884: int type)
885: {
886: unsigned int actual; /* this many things */
887: int i;
888:
889: vm_size_t size, size_needed;
890: vm_offset_t addr;
891:
892: if (pset == PROCESSOR_SET_NULL)
893: return KERN_INVALID_ARGUMENT;
894:
895: size = 0; addr = 0;
896:
897: for (;;) {
898: pset_lock(pset);
899: if (!pset->active) {
900: pset_unlock(pset);
901: return KERN_FAILURE;
902: }
903:
904: if (type == THING_TASK)
905: actual = pset->task_count;
906: else
907: actual = pset->thread_count;
908:
909: /* do we have the memory we need? */
910:
911: size_needed = actual * sizeof(mach_port_t);
912: if (size_needed <= size)
913: break;
914:
915: /* unlock the pset and allocate more memory */
916: pset_unlock(pset);
917:
918: if (size != 0)
919: kfree(addr, size);
920:
921: assert(size_needed > 0);
922: size = size_needed;
923:
924: addr = kalloc(size);
925: if (addr == 0)
926: return KERN_RESOURCE_SHORTAGE;
927: }
928:
929: /* OK, have memory and the processor_set is locked & active */
930:
931: switch (type) {
932: case THING_TASK: {
933: task_t *tasks = (task_t *) addr;
934: task_t task;
935:
936: for (i = 0, task = (task_t) queue_first(&pset->tasks);
937: i < actual;
938: i++, task = (task_t) queue_next(&task->pset_tasks)) {
939: /* take ref for convert_task_to_port */
940: task_reference(task);
941: tasks[i] = task;
942: }
943: assert(queue_end(&pset->tasks, (queue_entry_t) task));
944: break;
945: }
946:
947: case THING_THREAD: {
948: thread_t *threads = (thread_t *) addr;
949: thread_t thread;
950:
951: for (i = 0, thread = (thread_t) queue_first(&pset->threads);
952: i < actual;
953: i++,
954: thread = (thread_t) queue_next(&thread->pset_threads)) {
955: /* take ref for convert_thread_to_port */
956: thread_reference(thread);
957: threads[i] = thread;
958: }
959: assert(queue_end(&pset->threads, (queue_entry_t) thread));
960: break;
961: }
962: }
963:
964: /* can unlock processor set now that we have the task/thread refs */
965: pset_unlock(pset);
966:
967: if (actual == 0) {
968: /* no things, so return null pointer and deallocate memory */
969: *thing_list = 0;
970: *count = 0;
971:
972: if (size != 0)
973: kfree(addr, size);
974: } else {
975: /* if we allocated too much, must copy */
976:
977: if (size_needed < size) {
978: vm_offset_t newaddr;
979:
980: newaddr = kalloc(size_needed);
981: if (newaddr == 0) {
982: switch (type) {
983: case THING_TASK: {
984: task_t *tasks = (task_t *) addr;
985:
986: for (i = 0; i < actual; i++)
987: task_deallocate(tasks[i]);
988: break;
989: }
990:
991: case THING_THREAD: {
992: thread_t *threads = (thread_t *) addr;
993:
994: for (i = 0; i < actual; i++)
995: thread_deallocate(threads[i]);
996: break;
997: }
998: }
999: kfree(addr, size);
1000: return KERN_RESOURCE_SHORTAGE;
1001: }
1002:
1003: bcopy((char *) addr, (char *) newaddr, size_needed);
1004: kfree(addr, size);
1005: addr = newaddr;
1006: }
1007:
1008: *thing_list = (mach_port_t *) addr;
1009: *count = actual;
1010:
1011: /* do the conversion that Mig should handle */
1012:
1013: switch (type) {
1014: case THING_TASK: {
1015: task_t *tasks = (task_t *) addr;
1016:
1017: for (i = 0; i < actual; i++)
1018: ((mach_port_t *) tasks)[i] =
1019: (mach_port_t)convert_task_to_port(tasks[i]);
1020: break;
1021: }
1022:
1023: case THING_THREAD: {
1024: thread_t *threads = (thread_t *) addr;
1025:
1026: for (i = 0; i < actual; i++)
1027: ((mach_port_t *) threads)[i] =
1028: (mach_port_t)convert_thread_to_port(threads[i]);
1029: break;
1030: }
1031: }
1032: }
1033:
1034: return KERN_SUCCESS;
1035: }
1036:
1037:
1038: /*
1039: * processor_set_tasks:
1040: *
1041: * List all tasks in the processor set.
1042: */
1043: kern_return_t
1044: processor_set_tasks(
1045: processor_set_t pset,
1046: task_array_t *task_list,
1047: natural_t *count)
1048: {
1049: return processor_set_things(pset, task_list, count, THING_TASK);
1050: }
1051:
1052: /*
1053: * processor_set_threads:
1054: *
1055: * List all threads in the processor set.
1056: */
1057: kern_return_t
1058: processor_set_threads(
1059: processor_set_t pset,
1060: thread_array_t *thread_list,
1061: natural_t *count)
1062: {
1063: return processor_set_things(pset, thread_list, count, THING_THREAD);
1064: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.