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