Annotation of XNU/osfmk/kern/processor.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.