Annotation of Gnu-Mach/kern/processor.c, revision 1.1.1.6

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

unix.superglobalmegacorp.com

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