Annotation of kernel/kern/processor.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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