|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989,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:
53: /*
54: * processor.c: processor and processor_set manipulation routines.
55: */
56:
57: #include <cpus.h>
58: #include <mach_host.h>
59:
60: #include <mach/boolean.h>
61: #include <mach/policy.h>
62: #include <mach/processor_info.h>
63: #include <mach/vm_param.h>
64: #include <kern/cpu_number.h>
65: #include <kern/host.h>
66: #include <kern/machine.h>
67: #include <kern/misc_protos.h>
68: #include <kern/processor.h>
69: #include <kern/sched.h>
70: #include <kern/task.h>
71: #include <kern/thread.h>
72: #include <kern/ipc_host.h>
73: #include <kern/ipc_tt.h>
74: #include <ipc/ipc_port.h>
75: #include <kern/kalloc.h>
76: #include <kern/rtmalloc.h>
77:
78: #if MACH_HOST
79: #include <kern/zalloc.h>
80: zone_t pset_zone;
81: #endif /* MACH_HOST */
82:
83: #include <kern/sf.h>
84: #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/
85:
86: /*
87: * Exported interface
88: */
89: #include <mach/mach_host_server.h>
90:
91: /*
92: * Exported variables.
93: */
94: struct processor_set default_pset;
95: struct processor processor_array[NCPUS];
96:
97: queue_head_t all_psets;
98: int all_psets_count;
99: decl_mutex_data(, all_psets_lock)
100:
101: processor_t master_processor;
102: processor_t processor_ptr[NCPUS];
103:
104: /* Forwards */
105: void pset_init(
106: processor_set_t pset);
107:
108: void processor_init(
109: register processor_t pr,
110: int slot_num);
111:
112: void quantum_set(
113: processor_set_t pset);
114:
115: kern_return_t processor_set_base(
116: processor_set_t pset,
117: policy_t policy,
118: policy_base_t base,
119: boolean_t change);
120:
121: kern_return_t processor_set_limit(
122: processor_set_t pset,
123: policy_t policy,
124: policy_limit_t limit,
125: boolean_t change);
126:
127: kern_return_t processor_set_things(
128: processor_set_t pset,
129: mach_port_t **thing_list,
130: mach_msg_type_number_t *count,
131: int type);
132:
133:
134: /*
135: * Bootstrap the processor/pset system so the scheduler can run.
136: */
137: void
138: pset_sys_bootstrap(void)
139: {
140: register int i;
141:
142: pset_init(&default_pset);
143: default_pset.empty = FALSE;
144: for (i = 0; i < NCPUS; i++) {
145: /*
146: * Initialize processor data structures.
147: * Note that cpu_to_processor(i) is processor_ptr[i].
148: */
149: processor_ptr[i] = &processor_array[i];
150: processor_init(processor_ptr[i], i);
151: }
152: master_processor = cpu_to_processor(master_cpu);
153: queue_init(&all_psets);
154: mutex_init(&all_psets_lock, ETAP_THREAD_PSET_ALL);
155: queue_enter(&all_psets, &default_pset, processor_set_t, all_psets);
156: all_psets_count = 1;
157: default_pset.active = TRUE;
158: default_pset.empty = FALSE;
159:
160: /*
161: * Note: the default_pset has a max_priority of BASEPRI_USER.
162: * Internal kernel threads override this in kernel_thread.
163: */
164: }
165:
166: #if MACH_HOST
167: /*
168: * Rest of pset system initializations.
169: */
170: void
171: pset_sys_init(void)
172: {
173: register int i;
174: register processor_t processor;
175:
176: /*
177: * Allocate the zone for processor sets.
178: */
179: pset_zone = zinit(sizeof(struct processor_set), 128*PAGE_SIZE,
180: PAGE_SIZE, "processor sets");
181:
182: /*
183: * Give each processor a control port.
184: * The master processor already has one.
185: */
186: for (i = 0; i < NCPUS; i++) {
187: processor = cpu_to_processor(i);
188: if (processor != master_processor &&
189: machine_slot[i].is_cpu)
190: {
191: ipc_processor_init(processor);
192: ipc_processor_enable(processor);
193: }
194: }
195: }
196: #endif /* MACH_HOST */
197:
198: /*
199: * Initialize the given processor_set structure.
200: */
201:
202: void pset_init(
203: register processor_set_t pset)
204: {
205: int i;
206:
207: /* setup run-queues */
208: simple_lock_init(&pset->runq.lock, ETAP_THREAD_PSET_RUNQ);
209: pset->runq.count = 0;
210: pset->runq.depress_count = 0;
211: for (i = 0; i < NRQBM; i++) {
212: pset->runq.bitmap[i] = 0;
213: }
214: setbit(MAXPRI - IDLEPRI, pset->runq.bitmap);
215: pset->runq.highq = IDLEPRI;
216: for (i = 0; i < NRQS; i++) {
217: queue_init(&(pset->runq.runq[i]));
218: }
219:
220: queue_init(&pset->idle_queue);
221: pset->idle_count = 0;
222: simple_lock_init(&pset->idle_lock, ETAP_THREAD_PSET_IDLE);
223: queue_init(&pset->processors);
224: pset->processor_count = 0;
225: pset->empty = TRUE;
226: queue_init(&pset->tasks);
227: pset->task_count = 0;
228: queue_init(&pset->threads);
229: pset->thread_count = 0;
230: pset->ref_count = 1;
231: queue_init(&pset->all_psets);
232: pset->active = FALSE;
233: mutex_init(&pset->lock, ETAP_THREAD_PSET);
234: pset->pset_self = IP_NULL;
235: pset->pset_name_self = IP_NULL;
236: pset->max_priority = BASEPRI_USER;
237: pset->policies = POLICY_TIMESHARE | POLICY_FIFO | POLICY_RR;
238: pset->set_quantum = min_quantum;
239:
240: pset->quantum_adj_index = 0;
241: simple_lock_init(&pset->quantum_adj_lock, ETAP_THREAD_PSET_QUANT);
242:
243: for (i = 0; i <= NCPUS; i++) {
244: pset->machine_quantum[i] = min_quantum;
245: }
246:
247: pset->mach_factor = 0;
248: pset->load_average = 0;
249: pset->sched_load = SCHED_SCALE; /* i.e. 1 */
250:
251: pset->policy_default = POLICY_TIMESHARE;
252: pset->policy_limit.ts.max_priority = BASEPRI_USER;
253: pset->policy_limit.rr.max_priority = BASEPRI_USER;
254: pset->policy_limit.fifo.max_priority = BASEPRI_USER;
255: pset->policy_base.ts.base_priority = BASEPRI_USER;
256: pset->policy_base.rr.base_priority = BASEPRI_USER;
257: pset->policy_base.rr.quantum = min_quantum;
258: pset->policy_base.fifo.base_priority = BASEPRI_USER;
259: }
260:
261:
262: /*
263: * Find the pset's maximum priority (limit) for the given policy.
264: * This is for internal use only.
265: */
266:
267: int
268: pset_max_priority(
269: processor_set_t pset,
270: policy_t policy)
271: {
272: int max = BASEPRI_USER;
273:
274: if (invalid_policy(policy) || pset == PROCESSOR_SET_NULL)
275: return max;
276:
277: switch (policy) {
278: case POLICY_TIMESHARE:
279: max = pset->policy_limit.ts.max_priority;
280: break;
281:
282: case POLICY_RR:
283: max = pset->policy_limit.rr.max_priority;
284: break;
285:
286: case POLICY_FIFO:
287: max = pset->policy_limit.fifo.max_priority;
288: break;
289: }
290:
291: return max;
292: }
293:
294: /*
295: * Find the pset's base priority for the given policy. This is
296: * for internal use only.
297: */
298:
299: int
300: pset_base_priority(
301: processor_set_t pset,
302: policy_t policy)
303: {
304: int base = BASEPRI_USER;
305:
306: if (invalid_policy(policy) || pset == PROCESSOR_SET_NULL)
307: return base;
308:
309: switch (policy) {
310: case POLICY_TIMESHARE:
311: base = pset->policy_base.ts.base_priority;
312: break;
313:
314: case POLICY_RR:
315: base = pset->policy_base.rr.base_priority;
316: break;
317:
318: case POLICY_FIFO:
319: base = pset->policy_base.fifo.base_priority;
320: break;
321: }
322:
323: return base;
324: }
325:
326: /*
327: * Find the pset's sched data for the given policy. This is
328: * for internal use only.
329: */
330:
331: int
332: pset_sched_data(
333: processor_set_t pset,
334: policy_t policy)
335: {
336: int temp, data = 0;
337:
338: if (invalid_policy(policy) || pset == PROCESSOR_SET_NULL)
339: return data;
340:
341: switch (policy) {
342: case POLICY_TIMESHARE:
343: data = 0;
344: break;
345:
346: case POLICY_RR:
347: temp = pset->policy_base.rr.quantum * 1000;
348: if (temp % tick)
349: temp += tick;
350: data = temp/tick;
351: break;
352:
353: case POLICY_FIFO:
354: data = 0;
355: break;
356: }
357:
358: return data;
359: }
360:
361: /*
362: * Initialize the given processor structure for the processor in
363: * the slot specified by slot_num.
364: */
365:
366: void
367: processor_init(
368: register processor_t pr,
369: int slot_num)
370: {
371: int i;
372:
373: /* setup run-queues */
374: simple_lock_init(&pr->runq.lock, ETAP_THREAD_PROC_RUNQ);
375: pr->runq.count = 0;
376: pr->runq.depress_count = 0;
377: for (i = 0; i < NRQBM; i++) {
378: pr->runq.bitmap[i] = 0;
379: }
380: setbit(MAXPRI - IDLEPRI, pr->runq.bitmap);
381: pr->runq.highq = IDLEPRI;
382: for (i = 0; i < NRQS; i++) {
383: queue_init(&(pr->runq.runq[i]));
384: }
385:
386: queue_init(&pr->processor_queue);
387: pr->state = PROCESSOR_OFF_LINE;
388: pr->next_thread = THREAD_NULL;
389: pr->idle_thread = THREAD_NULL;
390: pr->quantum = 0;
391: pr->first_quantum = FALSE;
392: pr->last_quantum = 0;
393: pr->processor_set = PROCESSOR_SET_NULL;
394: pr->processor_set_next = PROCESSOR_SET_NULL;
395: queue_init(&pr->processors);
396: simple_lock_init(&pr->lock, ETAP_THREAD_PROC);
397: pr->processor_self = IP_NULL;
398: pr->slot_num = slot_num;
399: }
400:
401: /*
402: * pset_remove_processor() removes a processor from a processor_set.
403: * It can only be called on the current processor. Caller must
404: * hold lock on current processor and processor set.
405: */
406:
407: void
408: pset_remove_processor(
409: processor_set_t pset,
410: processor_t processor)
411: {
412: if (pset != processor->processor_set)
413: panic("pset_remove_processor: wrong pset");
414:
415: queue_remove(&pset->processors, processor, processor_t, processors);
416: processor->processor_set = PROCESSOR_SET_NULL;
417: pset->processor_count--;
418: quantum_set(pset);
419: }
420:
421: /*
422: * pset_add_processor() adds a processor to a processor_set.
423: * It can only be called on the current processor. Caller must
424: * hold lock on curent processor and on pset. No reference counting on
425: * processors. Processor reference to pset is implicit.
426: */
427:
428: void
429: pset_add_processor(
430: processor_set_t pset,
431: processor_t processor)
432: {
433: queue_enter(&pset->processors, processor, processor_t, processors);
434: processor->processor_set = pset;
435: pset->processor_count++;
436: quantum_set(pset);
437: }
438:
439: /*
440: * pset_remove_task() removes a task from a processor_set.
441: * Caller must hold locks on pset and task. Pset reference count
442: * is not decremented; caller must explicitly pset_deallocate.
443: */
444:
445: void
446: pset_remove_task(
447: processor_set_t pset,
448: task_t task)
449: {
450: if (pset != task->processor_set)
451: return;
452:
453: queue_remove(&pset->tasks, task, task_t, pset_tasks);
454: task->processor_set = PROCESSOR_SET_NULL;
455: pset->task_count--;
456: }
457:
458: /*
459: * pset_add_task() adds a task to a processor_set.
460: * Caller must hold locks on pset and task. Pset references to
461: * tasks are implicit.
462: */
463:
464: void
465: pset_add_task(
466: processor_set_t pset,
467: task_t task)
468: {
469: queue_enter(&pset->tasks, task, task_t, pset_tasks);
470: task->processor_set = pset;
471: pset->task_count++;
472: pset->ref_count++;
473: }
474:
475: /*
476: * pset_remove_thread() removes a thread from a processor_set.
477: * Caller must hold locks on pset and thread. Pset reference count
478: * is not decremented; caller must explicitly pset_deallocate.
479: */
480:
481: void
482: pset_remove_thread(
483: processor_set_t pset,
484: thread_t thread)
485: {
486: queue_remove(&pset->threads, thread, thread_t, pset_threads);
487: thread->processor_set = PROCESSOR_SET_NULL;
488: pset->thread_count--;
489: }
490:
491: /*
492: * pset_add_thread() adds a thread to a processor_set.
493: * Caller must hold locks on pset and thread. Pset references to
494: * threads are implicit.
495: */
496:
497: void
498: pset_add_thread(
499: processor_set_t pset,
500: thread_t thread)
501: {
502: queue_enter(&pset->threads, thread, thread_t, pset_threads);
503: thread->processor_set = pset;
504: pset->thread_count++;
505: pset->ref_count++;
506: }
507:
508: /*
509: * thread_change_psets() changes the pset of a thread. Caller must
510: * hold locks on both psets and thread. The old pset must be
511: * explicitly pset_deallocat()'ed by caller.
512: */
513:
514: void
515: thread_change_psets(
516: thread_t thread,
517: processor_set_t old_pset,
518: processor_set_t new_pset)
519: {
520: queue_remove(&old_pset->threads, thread, thread_t, pset_threads);
521: old_pset->thread_count--;
522: queue_enter(&new_pset->threads, thread, thread_t, pset_threads);
523: thread->processor_set = new_pset;
524: new_pset->thread_count++;
525: new_pset->ref_count++;
526: }
527:
528: /*
529: * pset_deallocate:
530: *
531: * Remove one reference to the processor set. Destroy processor_set
532: * if this was the last reference.
533: */
534:
535: void
536: pset_deallocate(
537: processor_set_t pset)
538: {
539: if (pset == PROCESSOR_SET_NULL)
540: return;
541:
542: pset_lock(pset);
543: if (--pset->ref_count > 0) {
544: pset_unlock(pset);
545: return;
546: }
547: #if !MACH_HOST
548: panic("pset_deallocate: default_pset destroyed");
549: #endif /* !MACH_HOST */
550: #if MACH_HOST
551: /*
552: * Reference count is zero, however the all_psets list
553: * holds an implicit reference and may make new ones.
554: * Its lock also dominates the pset lock. To check for this,
555: * temporarily restore one reference, and then lock the
556: * other structures in the right order.
557: */
558: pset->ref_count = 1;
559: pset_unlock(pset);
560:
561: mutex_lock(&all_psets_lock);
562: pset_lock(pset);
563: if (--pset->ref_count > 0) {
564: /*
565: * Made an extra reference.
566: */
567: pset_unlock(pset);
568: mutex_unlock(&all_psets_lock);
569: return;
570: }
571:
572: /*
573: * Ok to destroy pset. Make a few paranoia checks.
574: */
575:
576: if ((pset == &default_pset) || (pset->thread_count > 0) ||
577: (pset->task_count > 0) || pset->processor_count > 0) {
578: panic("pset_deallocate: destroy default or active pset");
579: }
580: /*
581: * Remove from all_psets queue.
582: */
583: queue_remove(&all_psets, pset, processor_set_t, all_psets);
584: all_psets_count--;
585:
586: pset_unlock(pset);
587: mutex_unlock(&all_psets_lock);
588:
589: /*
590: * That's it, free data structure.
591: */
592: zfree(pset_zone, (vm_offset_t)pset);
593: #endif /* MACH_HOST */
594: }
595:
596: /*
597: * pset_reference:
598: *
599: * Add one reference to the processor set.
600: */
601:
602: void
603: pset_reference(
604: processor_set_t pset)
605: {
606: pset_lock(pset);
607: pset->ref_count++;
608: pset_unlock(pset);
609: }
610:
611: kern_return_t
612: processor_info(
613: register processor_t processor,
614: processor_flavor_t flavor,
615: host_t *host,
616: processor_info_t info,
617: mach_msg_type_number_t *count)
618: {
619: register int i, slot_num, state;
620: register processor_basic_info_t basic_info;
621: register processor_cpu_load_info_t cpu_load_info;
622: kern_return_t kr;
623:
624: if (processor == PROCESSOR_NULL)
625: return(KERN_INVALID_ARGUMENT);
626:
627: slot_num = processor->slot_num;
628:
629: switch (flavor) {
630:
631: case PROCESSOR_BASIC_INFO:
632: {
633: if (*count < PROCESSOR_BASIC_INFO_COUNT)
634: return(KERN_FAILURE);
635:
636: basic_info = (processor_basic_info_t) info;
637: basic_info->cpu_type = machine_slot[slot_num].cpu_type;
638: basic_info->cpu_subtype = machine_slot[slot_num].cpu_subtype;
639: state = processor->state;
640: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE)
641: basic_info->running = FALSE;
642: else
643: basic_info->running = TRUE;
644: basic_info->slot_num = slot_num;
645: if (processor == master_processor)
646: basic_info->is_master = TRUE;
647: else
648: basic_info->is_master = FALSE;
649:
650: *count = PROCESSOR_BASIC_INFO_COUNT;
651: *host = &realhost;
652: return(KERN_SUCCESS);
653: }
654: case PROCESSOR_CPU_LOAD_INFO:
655: {
656: if (*count < PROCESSOR_CPU_LOAD_INFO_COUNT)
657: return(KERN_FAILURE);
658:
659: cpu_load_info = (processor_cpu_load_info_t) info;
660: for (i=0;i<CPU_STATE_MAX;i++)
661: cpu_load_info->cpu_ticks[i] = machine_slot[slot_num].cpu_ticks[i];
662:
663: *count = PROCESSOR_CPU_LOAD_INFO_COUNT;
664: *host = &realhost;
665: return(KERN_SUCCESS);
666: }
667: default:
668: {
669: kr=cpu_info(flavor, slot_num, info, count);
670: if (kr == KERN_SUCCESS)
671: *host = &realhost;
672: return(kr);
673: }
674: }
675: }
676:
677: kern_return_t
678: processor_start(
679: processor_t processor)
680: {
681: if (processor == PROCESSOR_NULL)
682: return(KERN_INVALID_ARGUMENT);
683:
684: /* TODO: Test if the target processor has already been started */
685: /* TODO: boot_processor : for now, assume cpu 0 */
686: if (processor->slot_num != 0)
687: {
688: thread_t thread;
689: sched_policy_t *policy;
690: sf_return_t sfr;
691: spl_t s;
692: extern void start_cpu_thread(void);
693:
694: thread = kernel_thread_with_attributes( kernel_task, SP_ATTRIBUTES_NULL, start_cpu_thread, FALSE);
695: s = splsched();
696: thread_lock(thread);
697: thread_bind_locked(thread, processor);
698: processor->next_thread = thread;
699: thread->state |= TH_RUN;
700: /*(void) thread_resume(thread->top_act);*/
701:
702: /* get pointer to scheduling policy "object" */
703: policy = &sched_policy[thread->policy];
704:
705: sfr = policy->sp_ops.sp_thread_unblock(policy, thread);
706: assert(sfr == SF_SUCCESS);
707: thread_unlock(thread);
708: splx(s);
709: }
710:
711: return(cpu_start(processor->slot_num));
712: }
713:
714: kern_return_t
715: processor_exit(
716: processor_t processor)
717: {
718: if (processor == PROCESSOR_NULL)
719: return(KERN_INVALID_ARGUMENT);
720:
721: return(processor_shutdown(processor));
722: }
723:
724: kern_return_t
725: processor_control(
726: processor_t processor,
727: processor_info_t info,
728: mach_msg_type_number_t count)
729: {
730: if (processor == PROCESSOR_NULL)
731: return(KERN_INVALID_ARGUMENT);
732:
733: return(cpu_control(processor->slot_num, info, count));
734: }
735:
736: /*
737: * Precalculate the appropriate system quanta based on load. The
738: * index into machine_quantum is the number of threads on the
739: * processor set queue. It is limited to the number of processors in
740: * the set.
741: */
742:
743: void
744: quantum_set(
745: processor_set_t pset)
746: {
747: #if NCPUS > 1
748: register int i, ncpus;
749:
750: ncpus = pset->processor_count;
751:
752: for (i=1; i <= ncpus; i++)
753: pset->machine_quantum[i] = ((min_quantum * ncpus) + (i / 2)) / i ;
754:
755: pset->machine_quantum[0] = pset->machine_quantum[1];
756:
757: i = (pset->runq.count > ncpus) ? ncpus : pset->runq.count;
758: pset->set_quantum = pset->machine_quantum[i];
759: #else /* NCPUS > 1 */
760: default_pset.set_quantum = min_quantum;
761: #endif /* NCPUS > 1 */
762: }
763:
764: #if MACH_HOST
765: /*
766: * processor_set_create:
767: *
768: * Create and return a new processor set.
769: */
770:
771: kern_return_t
772: processor_set_create(
773: host_t host,
774: processor_set_t *new_set,
775: processor_set_t *new_name)
776: {
777: processor_set_t pset;
778:
779: if (host == HOST_NULL)
780: return(KERN_INVALID_ARGUMENT);
781: pset = (processor_set_t) zalloc(pset_zone);
782: pset_init(pset);
783: pset_reference(pset); /* for new_set out argument */
784: pset_reference(pset); /* for new_name out argument */
785: ipc_pset_init(pset);
786: pset->active = TRUE;
787:
788: mutex_lock(&all_psets_lock);
789: queue_enter(&all_psets, pset, processor_set_t, all_psets);
790: all_psets_count++;
791: mutex_unlock(&all_psets_lock);
792:
793: ipc_pset_enable(pset);
794:
795: *new_set = pset;
796: *new_name = pset;
797: return(KERN_SUCCESS);
798: }
799:
800: /*
801: * processor_set_destroy:
802: *
803: * destroy a processor set. Any tasks, threads or processors
804: * currently assigned to it are reassigned to the default pset.
805: */
806: kern_return_t
807: processor_set_destroy(
808: processor_set_t pset)
809: {
810: register queue_entry_t elem;
811: register queue_head_t *list;
812:
813: if (pset == PROCESSOR_SET_NULL || pset == &default_pset)
814: return(KERN_INVALID_ARGUMENT);
815:
816: /*
817: * Handle multiple termination race. First one through sets
818: * active to FALSE and disables ipc access.
819: */
820: pset_lock(pset);
821: if (!(pset->active)) {
822: pset_unlock(pset);
823: return(KERN_FAILURE);
824: }
825:
826: pset->active = FALSE;
827: ipc_pset_disable(pset);
828:
829:
830: /*
831: * Now reassign everything in this set to the default set.
832: */
833:
834: if (pset->task_count > 0) {
835: list = &pset->tasks;
836: while (!queue_empty(list)) {
837: elem = queue_first(list);
838: task_reference((task_t) elem);
839: pset_unlock(pset);
840: task_assign((task_t) elem, &default_pset, FALSE);
841: task_deallocate((task_t) elem);
842: pset_lock(pset);
843: }
844: }
845:
846: if (pset->thread_count > 0) {
847: list = &pset->threads;
848: while (!queue_empty(list)) {
849: thread_t thread;
850: thread_act_t thr_act;
851:
852: elem = queue_first(list);
853: thread = (thread_t)elem;
854: /*
855: * Get top activation of thread safely.
856: */
857: thr_act = thread_lock_act(thread);
858: /*
859: * Inline thread_assign() here to avoid silly double
860: * locking.
861: */
862: thread_freeze(thread);
863: thread_doassign(thread, &default_pset, TRUE);
864: /*
865: * All thread-related locks released at this point.
866: */
867: pset_lock(pset);
868: }
869: }
870:
871: if (pset->processor_count > 0) {
872: list = &pset->processors;
873: while(!queue_empty(list)) {
874: elem = queue_first(list);
875: pset_unlock(pset);
876: processor_assign((processor_t) elem, &default_pset, TRUE);
877: pset_lock(pset);
878: }
879: }
880:
881: pset_unlock(pset);
882:
883: /*
884: * Destroy ipc state.
885: */
886: ipc_pset_terminate(pset);
887:
888: /*
889: * Deallocate pset's reference to itself.
890: */
891: pset_deallocate(pset);
892: return(KERN_SUCCESS);
893: }
894:
895: #else /* MACH_HOST */
896:
897: kern_return_t
898: processor_set_create(
899: host_t host,
900: processor_set_t *new_set,
901: processor_set_t *new_name)
902: {
903: #ifdef lint
904: host++; new_set++; new_name++;
905: #endif /* lint */
906: return(KERN_FAILURE);
907: }
908:
909: kern_return_t
910: processor_set_destroy(
911: processor_set_t pset)
912: {
913: #ifdef lint
914: pset++;
915: #endif /* lint */
916: return(KERN_FAILURE);
917: }
918:
919: #endif /* MACH_HOST */
920:
921: kern_return_t
922: processor_get_assignment(
923: processor_t processor,
924: processor_set_t *pset)
925: {
926: int state;
927:
928: state = processor->state;
929: if (state == PROCESSOR_SHUTDOWN || state == PROCESSOR_OFF_LINE)
930: return(KERN_FAILURE);
931:
932: *pset = processor->processor_set;
933: pset_reference(*pset);
934: return(KERN_SUCCESS);
935: }
936:
937: kern_return_t
938: processor_set_info(
939: processor_set_t pset,
940: int flavor,
941: host_t *host,
942: processor_set_info_t info,
943: mach_msg_type_number_t *count)
944: {
945: if (pset == PROCESSOR_SET_NULL)
946: return(KERN_INVALID_ARGUMENT);
947:
948: if (flavor == PROCESSOR_SET_BASIC_INFO) {
949: register processor_set_basic_info_t basic_info;
950:
951: if (*count < PROCESSOR_SET_BASIC_INFO_COUNT)
952: return(KERN_FAILURE);
953:
954: basic_info = (processor_set_basic_info_t) info;
955:
956: pset_lock(pset);
957: basic_info->processor_count = pset->processor_count;
958: basic_info->default_policy = pset->policy_default;
959: pset_unlock(pset);
960:
961: *count = PROCESSOR_SET_BASIC_INFO_COUNT;
962: *host = &realhost;
963: return(KERN_SUCCESS);
964: }
965: else if (flavor == PROCESSOR_SET_TIMESHARE_DEFAULT) {
966: register policy_timeshare_base_t ts_base;
967:
968: if (*count < POLICY_TIMESHARE_BASE_COUNT)
969: return(KERN_FAILURE);
970:
971: ts_base = (policy_timeshare_base_t) info;
972:
973: pset_lock(pset);
974: *ts_base = pset->policy_base.ts;
975: pset_unlock(pset);
976:
977: *count = POLICY_TIMESHARE_BASE_COUNT;
978: *host = &realhost;
979: return(KERN_SUCCESS);
980: }
981: else if (flavor == PROCESSOR_SET_FIFO_DEFAULT) {
982: register policy_fifo_base_t fifo_base;
983:
984: if (*count < POLICY_FIFO_BASE_COUNT)
985: return(KERN_FAILURE);
986:
987: fifo_base = (policy_fifo_base_t) info;
988:
989: pset_lock(pset);
990: *fifo_base = pset->policy_base.fifo;
991: pset_unlock(pset);
992:
993: *count = POLICY_FIFO_BASE_COUNT;
994: *host = &realhost;
995: return(KERN_SUCCESS);
996: }
997: else if (flavor == PROCESSOR_SET_RR_DEFAULT) {
998: register policy_rr_base_t rr_base;
999:
1000: if (*count < POLICY_RR_BASE_COUNT)
1001: return(KERN_FAILURE);
1002:
1003: rr_base = (policy_rr_base_t) info;
1004:
1005: pset_lock(pset);
1006: *rr_base = pset->policy_base.rr;
1007: pset_unlock(pset);
1008:
1009: *count = POLICY_RR_BASE_COUNT;
1010: *host = &realhost;
1011: return(KERN_SUCCESS);
1012: }
1013: else if (flavor == PROCESSOR_SET_TIMESHARE_LIMITS) {
1014: register policy_timeshare_limit_t ts_limit;
1015:
1016: if (*count < POLICY_TIMESHARE_LIMIT_COUNT)
1017: return(KERN_FAILURE);
1018:
1019: ts_limit = (policy_timeshare_limit_t) info;
1020:
1021: pset_lock(pset);
1022: *ts_limit = pset->policy_limit.ts;
1023: pset_unlock(pset);
1024:
1025: *count = POLICY_TIMESHARE_LIMIT_COUNT;
1026: *host = &realhost;
1027: return(KERN_SUCCESS);
1028: }
1029: else if (flavor == PROCESSOR_SET_FIFO_LIMITS) {
1030: register policy_fifo_limit_t fifo_limit;
1031:
1032: if (*count < POLICY_FIFO_LIMIT_COUNT)
1033: return(KERN_FAILURE);
1034:
1035: fifo_limit = (policy_fifo_limit_t) info;
1036:
1037: pset_lock(pset);
1038: *fifo_limit = pset->policy_limit.fifo;
1039: pset_unlock(pset);
1040:
1041: *count = POLICY_FIFO_LIMIT_COUNT;
1042: *host = &realhost;
1043: return(KERN_SUCCESS);
1044: }
1045: else if (flavor == PROCESSOR_SET_RR_LIMITS) {
1046: register policy_rr_limit_t rr_limit;
1047:
1048: if (*count < POLICY_RR_LIMIT_COUNT)
1049: return(KERN_FAILURE);
1050:
1051: rr_limit = (policy_rr_limit_t) info;
1052:
1053: pset_lock(pset);
1054: *rr_limit = pset->policy_limit.rr;
1055: pset_unlock(pset);
1056:
1057: *count = POLICY_RR_LIMIT_COUNT;
1058: *host = &realhost;
1059: return(KERN_SUCCESS);
1060: }
1061: else if (flavor == PROCESSOR_SET_ENABLED_POLICIES) {
1062: register int *enabled;
1063:
1064: if (*count < (sizeof(*enabled)/sizeof(int)))
1065: return(KERN_FAILURE);
1066:
1067: enabled = (int *) info;
1068:
1069: pset_lock(pset);
1070: *enabled = pset->policies;
1071: pset_unlock(pset);
1072:
1073: *count = sizeof(*enabled)/sizeof(int);
1074: *host = &realhost;
1075: return(KERN_SUCCESS);
1076: }
1077:
1078:
1079: *host = HOST_NULL;
1080: return(KERN_INVALID_ARGUMENT);
1081: }
1082:
1083: /*
1084: * processor_set_statistics
1085: *
1086: * Returns scheduling statistics for a processor set.
1087: */
1088: kern_return_t
1089: processor_set_statistics(
1090: processor_set_t pset,
1091: int flavor,
1092: processor_set_info_t info,
1093: mach_msg_type_number_t *count)
1094: {
1095: if (pset == PROCESSOR_SET_NULL)
1096: return (KERN_INVALID_PROCESSOR_SET);
1097:
1098: if (flavor == PROCESSOR_SET_LOAD_INFO) {
1099: register processor_set_load_info_t load_info;
1100:
1101: if (*count < PROCESSOR_SET_LOAD_INFO_COUNT)
1102: return(KERN_FAILURE);
1103:
1104: load_info = (processor_set_load_info_t) info;
1105:
1106: pset_lock(pset);
1107: load_info->task_count = pset->task_count;
1108: load_info->thread_count = pset->thread_count;
1109: load_info->mach_factor = pset->mach_factor;
1110: load_info->load_average = pset->load_average;
1111: pset_unlock(pset);
1112:
1113: *count = PROCESSOR_SET_LOAD_INFO_COUNT;
1114: return(KERN_SUCCESS);
1115: }
1116:
1117: return(KERN_INVALID_ARGUMENT);
1118: }
1119:
1120: /*
1121: * processor_set_max_priority:
1122: *
1123: * Specify max priority permitted on processor set. This affects
1124: * newly created and assigned threads. Optionally change existing
1125: * ones.
1126: */
1127: kern_return_t
1128: processor_set_max_priority(
1129: processor_set_t pset,
1130: int max_priority,
1131: boolean_t change_threads)
1132: {
1133: thread_act_t thr_act;
1134:
1135: if (pset == PROCESSOR_SET_NULL || invalid_pri(max_priority))
1136: return(KERN_INVALID_ARGUMENT);
1137:
1138: pset_lock(pset);
1139: pset->max_priority = max_priority;
1140:
1141: if (change_threads) {
1142: register queue_head_t *list;
1143: register thread_t thread;
1144:
1145: list = &pset->threads;
1146: thread = (thread_t) queue_first(list);
1147: while (!queue_end(list, (queue_entry_t) thread)) {
1148: thr_act = thread_lock_act(thread);
1149: /*** ??? fix me ***/
1150: assert(thread->sp_info != SP_INFO_NULL);
1151: if (((thread->policy == POLICY_TIMESHARE) ||
1152: (thread->policy == POLICY_RR) ||
1153: (thread->policy == POLICY_FIFO)) &&
1154: (((mk_sp_info_t)thread->sp_info)->max_priority < max_priority))
1155: {
1156: thread_max_priority_locked(thread, pset, max_priority);
1157: }
1158: thread_unlock_act(thread);
1159: thread = (thread_t) queue_next(&thread->pset_threads);
1160: }
1161: }
1162:
1163: pset_unlock(pset);
1164:
1165: return(KERN_SUCCESS);
1166: }
1167:
1168: /*
1169: * processor_set_policy_enable:
1170: *
1171: * Allow indicated policy on processor set.
1172: */
1173:
1174: kern_return_t
1175: processor_set_policy_enable(
1176: processor_set_t pset,
1177: int policy)
1178: {
1179: if ((pset == PROCESSOR_SET_NULL) || invalid_policy(policy))
1180: return(KERN_INVALID_ARGUMENT);
1181:
1182: pset_lock(pset);
1183: pset->policies |= policy;
1184: pset_unlock(pset);
1185:
1186: return(KERN_SUCCESS);
1187: }
1188:
1189: /*
1190: * processor_set_policy_disable:
1191: *
1192: * Forbid indicated policy on processor set. Time sharing cannot
1193: * be forbidden.
1194: */
1195:
1196: kern_return_t
1197: processor_set_policy_disable(
1198: processor_set_t pset,
1199: int policy,
1200: boolean_t change_threads)
1201: {
1202: thread_act_t thr_act;
1203:
1204: if ((pset == PROCESSOR_SET_NULL) || policy == POLICY_TIMESHARE ||
1205: invalid_policy(policy))
1206: return(KERN_INVALID_ARGUMENT);
1207:
1208: pset_lock(pset);
1209:
1210: /*
1211: * Check if policy enabled. Disable if so, then handle
1212: * change_threads.
1213: */
1214: if (pset->policies & policy) {
1215: pset->policies &= ~policy;
1216:
1217: if (change_threads) {
1218: register queue_head_t *list;
1219: register thread_t thread;
1220: policy_base_t base;
1221: policy_timeshare_base_data_t ts_data;
1222:
1223: base = (policy_base_t) &ts_data;
1224: ts_data.base_priority = 0;
1225: list = &pset->threads;
1226: thread = (thread_t) queue_first(list);
1227: while (!queue_end(list, (queue_entry_t) thread)) {
1228: thr_act = thread_lock_act(thread);
1229: if (thr_act && thread->policy == policy)
1230: thread_policy(thr_act, POLICY_TIMESHARE, base,
1231: POLICY_TIMESHARE_BASE_COUNT, FALSE);
1232: thread_unlock_act(thread);
1233: thread = (thread_t) queue_next(&thread->pset_threads);
1234: }
1235: }
1236: }
1237: pset_unlock(pset);
1238:
1239: return(KERN_SUCCESS);
1240: }
1241:
1242: #define THING_TASK 0
1243: #define THING_THREAD 1
1244:
1245: /*
1246: * processor_set_things:
1247: *
1248: * Common internals for processor_set_{threads,tasks}
1249: */
1250: kern_return_t
1251: processor_set_things(
1252: processor_set_t pset,
1253: mach_port_t **thing_list,
1254: mach_msg_type_number_t *count,
1255: int type)
1256: {
1257: unsigned int actual; /* this many things */
1258: int i;
1259: boolean_t rt = FALSE; /* ### This boolean is FALSE, because there
1260: * currently exists no mechanism to determine
1261: * whether or not the reply port is an RT port
1262: */
1263:
1264: vm_size_t size, size_needed;
1265: vm_offset_t addr;
1266:
1267: if (pset == PROCESSOR_SET_NULL)
1268: return KERN_INVALID_ARGUMENT;
1269:
1270: size = 0; addr = 0;
1271:
1272: for (;;) {
1273: pset_lock(pset);
1274: if (!pset->active) {
1275: pset_unlock(pset);
1276: return KERN_FAILURE;
1277: }
1278:
1279: if (type == THING_TASK)
1280: actual = pset->task_count;
1281: else
1282: actual = pset->thread_count;
1283:
1284: /* do we have the memory we need? */
1285:
1286: size_needed = actual * sizeof(mach_port_t);
1287: if (size_needed <= size)
1288: break;
1289:
1290: /* unlock the pset and allocate more memory */
1291: pset_unlock(pset);
1292:
1293: if (size != 0)
1294: KFREE(addr, size, rt);
1295:
1296: assert(size_needed > 0);
1297: size = size_needed;
1298:
1299: addr = KALLOC(size, rt);
1300: if (addr == 0)
1301: return KERN_RESOURCE_SHORTAGE;
1302: }
1303:
1304: /* OK, have memory and the processor_set is locked & active */
1305:
1306: switch (type) {
1307: case THING_TASK: {
1308: task_t *tasks = (task_t *) addr;
1309: task_t task;
1310:
1311: for (i = 0, task = (task_t) queue_first(&pset->tasks);
1312: i < actual;
1313: i++, task = (task_t) queue_next(&task->pset_tasks)) {
1314: /* take ref for convert_task_to_port */
1315: task_reference(task);
1316: tasks[i] = task;
1317: }
1318: assert(queue_end(&pset->tasks, (queue_entry_t) task));
1319: break;
1320: }
1321:
1322: case THING_THREAD: {
1323: thread_act_t *thr_acts = (thread_act_t *) addr;
1324: thread_t thread;
1325: thread_act_t thr_act;
1326: queue_head_t *list;
1327:
1328: list = &pset->threads;
1329: thread = (thread_t) queue_first(list);
1330: i = 0;
1331: while (i < actual && !queue_end(list, (queue_entry_t)thread)) {
1332: thr_act = thread_lock_act(thread);
1333: if (thr_act && thr_act->ref_count > 0) {
1334: /* take ref for convert_act_to_port */
1335: act_locked_act_reference(thr_act);
1336: thr_acts[i] = thr_act;
1337: i++;
1338: }
1339: thread_unlock_act(thread);
1340: thread = (thread_t) queue_next(&thread->pset_threads);
1341: }
1342: if (i < actual) {
1343: actual = i;
1344: size_needed = actual * sizeof(mach_port_t);
1345: }
1346: break;
1347: }
1348: }
1349:
1350: /* can unlock processor set now that we have the task/thread refs */
1351: pset_unlock(pset);
1352:
1353: if (actual == 0) {
1354: /* no things, so return null pointer and deallocate memory */
1355: *thing_list = 0;
1356: *count = 0;
1357:
1358: if (size != 0)
1359: KFREE(addr, size, rt);
1360: } else {
1361: /* if we allocated too much, must copy */
1362:
1363: if (size_needed < size) {
1364: vm_offset_t newaddr;
1365:
1366: newaddr = KALLOC(size_needed, rt);
1367: if (newaddr == 0) {
1368: switch (type) {
1369: case THING_TASK: {
1370: task_t *tasks = (task_t *) addr;
1371:
1372: for (i = 0; i < actual; i++)
1373: task_deallocate(tasks[i]);
1374: break;
1375: }
1376:
1377: case THING_THREAD: {
1378: thread_t *threads = (thread_t *) addr;
1379:
1380: for (i = 0; i < actual; i++)
1381: thread_deallocate(threads[i]);
1382: break;
1383: }
1384: }
1385: KFREE(addr, size, rt);
1386: return KERN_RESOURCE_SHORTAGE;
1387: }
1388:
1389: bcopy((char *) addr, (char *) newaddr, size_needed);
1390: KFREE(addr, size, rt);
1391: addr = newaddr;
1392: }
1393:
1394: *thing_list = (mach_port_t *) addr;
1395: *count = actual;
1396:
1397: /* do the conversion that Mig should handle */
1398:
1399: switch (type) {
1400: case THING_TASK: {
1401: task_t *tasks = (task_t *) addr;
1402:
1403: for (i = 0; i < actual; i++)
1404: (*thing_list)[i] = convert_task_to_port(tasks[i]);
1405: break;
1406: }
1407:
1408: case THING_THREAD: {
1409: thread_act_t *thr_acts = (thread_act_t *) addr;
1410:
1411: for (i = 0; i < actual; i++)
1412: (*thing_list)[i] = convert_act_to_port(thr_acts[i]);
1413: break;
1414: }
1415: }
1416: }
1417:
1418: return(KERN_SUCCESS);
1419: }
1420:
1421:
1422: /*
1423: * processor_set_tasks:
1424: *
1425: * List all tasks in the processor set.
1426: */
1427: kern_return_t
1428: processor_set_tasks(
1429: processor_set_t pset,
1430: task_array_t *task_list,
1431: mach_msg_type_number_t *count)
1432: {
1433: return(processor_set_things(pset, (mach_port_t **)task_list, count, THING_TASK));
1434: }
1435:
1436: /*
1437: * processor_set_threads:
1438: *
1439: * List all threads in the processor set.
1440: */
1441: kern_return_t
1442: processor_set_threads(
1443: processor_set_t pset,
1444: thread_array_t *thread_list,
1445: mach_msg_type_number_t *count)
1446: {
1447: return(processor_set_things(pset, (mach_port_t **)thread_list, count, THING_THREAD));
1448: }
1449:
1450: /*
1451: * processor_set_base:
1452: *
1453: * Specify per-policy base priority for a processor set. Set processor
1454: * set default policy to the given policy. This affects newly created
1455: * and assigned threads. Optionally change existing ones.
1456: */
1457: kern_return_t
1458: processor_set_base(
1459: processor_set_t pset,
1460: policy_t policy,
1461: policy_base_t base,
1462: boolean_t change)
1463: {
1464: int bc, lc;
1465: policy_limit_t limit;
1466: policy_rr_limit_data_t rr_limit;
1467: policy_fifo_limit_data_t fifo_limit;
1468: policy_timeshare_limit_data_t ts_limit;
1469: kern_return_t ret = KERN_SUCCESS;
1470:
1471: if (pset == PROCESSOR_SET_NULL)
1472: return(KERN_INVALID_PROCESSOR_SET);
1473:
1474: pset_lock(pset);
1475:
1476: switch (policy) {
1477: case POLICY_RR:
1478: {
1479: policy_rr_base_t rr_base = (policy_rr_base_t) base;
1480:
1481: if (invalid_pri(rr_base->base_priority)) {
1482: ret = KERN_INVALID_ARGUMENT;
1483: break;
1484: }
1485: bc = POLICY_RR_BASE_COUNT;
1486: lc = POLICY_RR_LIMIT_COUNT;
1487: pset->policy_base.rr = *rr_base;
1488: rr_limit.max_priority = rr_base->base_priority;
1489: limit = (policy_limit_t) &rr_limit;
1490: break;
1491: }
1492:
1493: case POLICY_FIFO:
1494: {
1495: policy_fifo_base_t fifo_base = (policy_fifo_base_t) base;
1496:
1497: if (invalid_pri(fifo_base->base_priority)) {
1498: ret = KERN_INVALID_ARGUMENT;
1499: break;
1500: }
1501: bc = POLICY_FIFO_BASE_COUNT;
1502: lc = POLICY_FIFO_LIMIT_COUNT;
1503: pset->policy_base.fifo = *fifo_base;
1504: fifo_limit.max_priority = fifo_base->base_priority;
1505: limit = (policy_limit_t) &fifo_limit;
1506: break;
1507: }
1508:
1509: case POLICY_TIMESHARE:
1510: {
1511: policy_timeshare_base_t ts_base =
1512: (policy_timeshare_base_t) base;
1513: if (invalid_pri(ts_base->base_priority)) {
1514: ret = KERN_INVALID_ARGUMENT;
1515: break;
1516: }
1517: bc = POLICY_TIMESHARE_BASE_COUNT;
1518: lc = POLICY_TIMESHARE_LIMIT_COUNT;
1519: pset->policy_base.ts = *ts_base;
1520: ts_limit.max_priority = ts_base->base_priority;
1521: limit = (policy_limit_t) &ts_limit;
1522: break;
1523: }
1524:
1525: default:
1526: ret = KERN_INVALID_POLICY;
1527: }
1528:
1529: if (ret != KERN_SUCCESS) {
1530: pset_unlock(pset);
1531: return (ret);
1532: }
1533:
1534: pset->policy_default = policy;
1535:
1536:
1537: /*
1538: * When changing the default policy and base priority, set the
1539: * limit priority equal to the base priority.
1540: */
1541: if (change) {
1542: register queue_head_t *list;
1543: register task_t task;
1544:
1545: list = &pset->tasks;
1546: task = (task_t) queue_first(list);
1547: while (!queue_end(list, (queue_entry_t) task)) {
1548: task_set_policy(task, pset, policy, base, bc,
1549: limit, lc, TRUE);
1550: task = (task_t) queue_next(&task->pset_tasks);
1551: }
1552: }
1553:
1554: pset_unlock(pset);
1555:
1556: return(ret);
1557: }
1558:
1559: /*
1560: * processor_set_limit:
1561: *
1562: * Specify per-policy limits for a processor set. This affects
1563: * newly created and assigned threads. Optionally change existing
1564: * ones.
1565: */
1566: kern_return_t
1567: processor_set_limit(
1568: processor_set_t pset,
1569: policy_t policy,
1570: policy_limit_t limit,
1571: boolean_t change)
1572: {
1573: int max;
1574: kern_return_t ret = KERN_SUCCESS;
1575: thread_act_t thr_act;
1576:
1577: if (pset == PROCESSOR_SET_NULL)
1578: return(KERN_INVALID_PROCESSOR_SET);
1579:
1580: pset_lock(pset);
1581:
1582: switch (policy) {
1583: case POLICY_RR:
1584: {
1585: policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit;
1586:
1587: max = rr_limit->max_priority;
1588: if (invalid_pri(max)) {
1589: ret = KERN_POLICY_LIMIT;
1590: break;
1591: }
1592: pset->policy_limit.rr = *rr_limit;
1593: break;
1594: }
1595:
1596: case POLICY_FIFO:
1597: {
1598: policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit;
1599:
1600: max = fifo_limit->max_priority;
1601: if (invalid_pri(max)) {
1602: ret = KERN_POLICY_LIMIT;
1603: break;
1604: }
1605: pset->policy_limit.fifo = *fifo_limit;
1606: break;
1607: }
1608:
1609: case POLICY_TIMESHARE:
1610: {
1611: policy_timeshare_limit_t ts_limit =
1612: (policy_timeshare_limit_t) limit;
1613:
1614: max = ts_limit->max_priority;
1615: if (invalid_pri(max)) {
1616: ret = KERN_POLICY_LIMIT;
1617: break;
1618: }
1619: pset->policy_limit.ts = *ts_limit;
1620: break;
1621: }
1622:
1623: default:
1624: ret = KERN_INVALID_POLICY;
1625: }
1626:
1627: if (ret != KERN_SUCCESS) {
1628: pset_unlock(pset);
1629: return(ret);
1630: }
1631:
1632: if (change) {
1633: register queue_head_t *list;
1634: register task_t task;
1635: register thread_t thread;
1636:
1637: /*
1638: * Only change the policy limits for those tasks and
1639: * threads whose policy matches our 'policy' variable.
1640: */
1641: list = &pset->tasks;
1642: task = (task_t) queue_first(list);
1643: while (!queue_end(list, (queue_entry_t) task)) {
1644: if (task->policy == policy)
1645: task_max_priority(task, pset, max);
1646: task = (task_t) queue_next(&task->pset_tasks);
1647: }
1648:
1649: list = &pset->threads;
1650: thread = (thread_t) queue_first(list);
1651: while (!queue_end(list, (queue_entry_t) thread)) {
1652: thr_act = thread_lock_act(thread);
1653: if (thr_act && thread->policy == policy)
1654: thread_max_priority(thr_act, pset, max);
1655: thread_unlock_act(thread);
1656: thread = (thread_t) queue_next(&thread->pset_threads);
1657: }
1658: }
1659:
1660: pset_unlock(pset);
1661:
1662: return(KERN_SUCCESS);
1663: }
1664:
1665:
1666: /*
1667: * New scheduling control interface
1668: */
1669:
1670: /*
1671: * processor_set_policy_control
1672: *
1673: * Controls the scheduling attributes governing the processor set.
1674: * Allows control of enabled policies, and per-policy base and limit
1675: * priorities.
1676: */
1677: kern_return_t
1678: processor_set_policy_control(
1679: processor_set_t pset,
1680: int flavor,
1681: processor_set_info_t policy_info,
1682: mach_msg_type_number_t count,
1683: boolean_t change)
1684: {
1685: policy_t policy, i;
1686: policy_base_t base;
1687: policy_limit_t limit;
1688: kern_return_t ret = KERN_SUCCESS;
1689:
1690: if (pset == PROCESSOR_SET_NULL)
1691: return (KERN_INVALID_PROCESSOR_SET);
1692:
1693: switch (flavor) {
1694: case PROCESSOR_SET_ENABLED_POLICIES:
1695: if (count != sizeof(policy_t))
1696: return(KERN_INVALID_ARGUMENT);
1697: policy = (policy_t) *policy_info;
1698: for (i = POLICY_TIMESHARE ; i <= POLICY_FIFO ; i = i << 1) {
1699: if (policy & i) {
1700: ret = processor_set_policy_enable(pset, i);
1701: if (ret != KERN_SUCCESS) return ret;
1702: } else {
1703: ret = processor_set_policy_disable(pset, i, change);
1704: if (ret != KERN_SUCCESS) return ret;
1705: }
1706: }
1707: return ret;
1708:
1709: case PROCESSOR_SET_RR_LIMITS:
1710: if (count != POLICY_RR_LIMIT_COUNT)
1711: return(KERN_INVALID_ARGUMENT);
1712: limit = (policy_limit_t) policy_info;
1713: ret = processor_set_limit(pset, POLICY_RR, limit, change);
1714: return ret;
1715:
1716: case PROCESSOR_SET_FIFO_LIMITS:
1717: if (count != POLICY_FIFO_LIMIT_COUNT)
1718: return(KERN_INVALID_ARGUMENT);
1719: limit = (policy_limit_t) policy_info;
1720: ret = processor_set_limit(pset, POLICY_FIFO, limit, change);
1721: return ret;
1722:
1723: case PROCESSOR_SET_TIMESHARE_LIMITS:
1724: if (count != POLICY_TIMESHARE_LIMIT_COUNT)
1725: return(KERN_INVALID_ARGUMENT);
1726: limit = (policy_limit_t) policy_info;
1727: ret = processor_set_limit(pset, POLICY_TIMESHARE, limit,
1728: change);
1729: return ret;
1730:
1731: case PROCESSOR_SET_RR_DEFAULT:
1732: if (count != POLICY_RR_BASE_COUNT)
1733: return(KERN_INVALID_ARGUMENT);
1734: base = (policy_base_t) policy_info;
1735: ret = processor_set_base(pset, POLICY_RR, base, change);
1736: return ret;
1737:
1738: case PROCESSOR_SET_FIFO_DEFAULT:
1739: if (count != POLICY_FIFO_BASE_COUNT)
1740: return(KERN_INVALID_ARGUMENT);
1741: base = (policy_base_t) policy_info;
1742: ret = processor_set_base(pset, POLICY_FIFO, base, change);
1743: return ret;
1744:
1745: case PROCESSOR_SET_TIMESHARE_DEFAULT:
1746: if (count != POLICY_TIMESHARE_BASE_COUNT)
1747: return(KERN_INVALID_ARGUMENT);
1748: base = (policy_base_t) policy_info;
1749: ret = processor_set_base(pset, POLICY_TIMESHARE,
1750: base, change);
1751: return ret;
1752:
1753: default:
1754: return (KERN_INVALID_ARGUMENT);
1755:
1756: }
1757:
1758: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.