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

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

unix.superglobalmegacorp.com

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