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

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  * 
                     25:  */
                     26: 
                     27: /***
                     28:  *** ??? The following lines were picked up when code was incorporated
                     29:  *** into this file from `kern/syscall_subr.c.'  These should be moved
                     30:  *** with the code if it moves again.  Otherwise, they should be trimmed,
                     31:  *** based on the files included above.
                     32:  ***/
                     33: 
                     34: #include <mach/boolean.h>
                     35: #include <mach/thread_switch.h>
                     36: #include <ipc/ipc_port.h>
                     37: #include <ipc/ipc_space.h>
                     38: #include <kern/counters.h>
                     39: #include <kern/ipc_kobject.h>
                     40: #include <kern/processor.h>
                     41: #include <kern/sched.h>
                     42: #include <kern/sched_prim.h>
                     43: #include <kern/spl.h>
                     44: #include <kern/task.h>
                     45: #include <kern/thread.h>
                     46: #include <kern/ast.h>
                     47: #include <mach/policy.h>
                     48: 
                     49: #include <kern/syscall_subr.h>
                     50: #include <mach/mach_host_server.h>
                     51: #include <mach/mach_syscalls.h>
                     52: 
                     53: /***
                     54:  *** ??? End of lines picked up when code was incorporated
                     55:  *** into this file from `kern/syscall_subr.c.'
                     56:  ***/
                     57: 
                     58: #include <kern/sf.h>
                     59: #include <kern/mk_sp.h>
                     60: #include <kern/misc_protos.h>
                     61: #include <kern/spl.h>
                     62: #include <kern/sched.h>
                     63: #include <kern/sched_prim.h>
                     64: #include <kern/assert.h>
                     65: #include <kern/thread.h>
                     66: #include <mach/mach_host_server.h>
                     67: 
                     68: /* Forwards */
                     69: void   _mk_sp_thread_depress_priority(
                     70:                        sf_object_t                     policy,
                     71:                        mach_msg_timeout_t      depress_time);
                     72: 
                     73: /***
                     74:  *** ??? The next two files supply the prototypes for `thread_set_policy()'
                     75:  *** and `thread_policy.'  These routines cannot stay here if they are
                     76:  *** exported Mach system calls.
                     77:  ***/
                     78: #include <mach/thread_act_server.h>
                     79: #include <mach/host_priv_server.h>
                     80: 
                     81: /*
                     82:  * Vector containing standard scheduling policy operations
                     83:  */
                     84: sp_ops_t       mk_sp_ops = {
                     85:                    _mk_sp_init,
                     86:                    _mk_sp_enable_processor_set,
                     87:                    _mk_sp_disable_processor_set,
                     88:                    _mk_sp_enable_processor,
                     89:                    _mk_sp_disable_processor,
                     90:                    _mk_sp_thread_update_mpri,
                     91:                    _mk_sp_thread_unblock,
                     92:                    _mk_sp_thread_done,
                     93:                    _mk_sp_thread_begin,
                     94:                    _mk_sp_thread_dispatch,
                     95:                    _mk_sp_thread_attach,
                     96:                    _mk_sp_thread_detach,
                     97:                    _mk_sp_thread_processor,
                     98:                    _mk_sp_thread_processor_set,
                     99:                    _mk_sp_thread_set,
                    100:                    _mk_sp_thread_get,
                    101:                    _mk_sp_db_print_sched_stats,
                    102:                    _mk_sp_swtch_pri,
                    103:                    _mk_sp_thread_switch,
                    104:                    _mk_sp_thread_depress_abort,
                    105:                    _mk_sp_thread_depress_timeout,
                    106:                    _mk_sp_task_attach,
                    107:                    _mk_sp_task_detach,
                    108:                    _mk_sp_task_policy,
                    109:                    _mk_sp_task_set_policy,
                    110:                    _mk_sp_task_set_sched,
                    111:                    _mk_sp_task_get_sched,
                    112:                    _mk_sp_thread_runnable,
                    113:                    _mk_sp_alarm_expired
                    114: };
                    115: 
                    116: /* Forwards */
                    117: kern_return_t  thread_policy_common(
                    118:                                        thread_t                thread,
                    119:                                        int                             policy,
                    120:                                        int                             data,
                    121:                                        processor_set_t pset);
                    122: 
                    123: void           _mk_sp_thread_dump(
                    124:                                        sched_thread_t  thread);
                    125: 
                    126: /*
                    127:  * Local variables
                    128:  */
                    129: #ifdef MACH_ASSERT
                    130: boolean_t      mk_sp_first_thread = TRUE;
                    131: #endif /* MACH_ASSERT */
                    132: 
                    133: /*
                    134:  * Counters to monitor policy-related events
                    135:  */
                    136: mach_counter_t c_mk_sp_init = 0,
                    137:                c_mk_sp_enable_processor_set = 0,
                    138:                c_mk_sp_disable_processor_set = 0,
                    139:                c_mk_sp_enable_processor = 0,
                    140:                c_mk_sp_disable_processor = 0,
                    141:                c_mk_sp_thread_update_mpri = 0,
                    142:                c_mk_sp_thread_unblock = 0,
                    143:                c_mk_sp_thread_done = 0,
                    144:                c_mk_sp_thread_begin = 0,
                    145:                c_mk_sp_thread_dispatch = 0,
                    146:                c_mk_sp_thread_attach = 0,
                    147:                c_mk_sp_thread_detach = 0,
                    148:                c_mk_sp_thread_processor = 0,
                    149:                c_mk_sp_thread_processor_set = 0,
                    150:                c_mk_sp_thread_set = 0,
                    151:                c_mk_sp_thread_get = 0,
                    152:                c_mk_sp_db_print_sched_stats = 0,
                    153:                c_mk_sp_swtch_pri = 0,
                    154:                c_mk_sp_thread_switch = 0,
                    155:                c_mk_sp_thread_depress_abort = 0,
                    156:                c_mk_sp_thread_depress_timeout = 0,
                    157:                c_mk_sp_task_attach = 0,
                    158:                c_mk_sp_task_detach = 0,
                    159:                c_mk_sp_task_policy = 0,
                    160:                c_mk_sp_task_set_policy = 0,
                    161:                c_mk_sp_task_set_sched = 0,
                    162:                c_mk_sp_task_get_sched = 0,
                    163:                c_mk_sp_thread_runnable = 0,
                    164:                c_mk_sp_alarm_expired = 0;
                    165: 
                    166: /*
                    167:  * Table to convert computed priorities into allocated priority range.
                    168:  */
                    169: int    convert_pri[NRQS];
                    170: 
                    171: /*
                    172:  * Lowest (normal -- i.e., not idle and not depressed) priority
                    173:  */
                    174: int    lpri = -1;
                    175: 
                    176: natural_t      min_quantum_ms;
                    177: 
                    178: /*
                    179:  * Standard operations for MK Scheduling Policy
                    180:  */
                    181: 
                    182: sf_return_t
                    183: _mk_sp_init(
                    184:        sf_object_t                     policy,
                    185:        int                                     policy_id,
                    186:        int                                     priority_mask_length,
                    187:        sf_priority_mask_t      priority_mask)
                    188: {
                    189:        int                                     i;
                    190:        int                                     first_metapri;
                    191:        int                                     last_metapri;
                    192: 
                    193:        counter(c_mk_sp_init++);
                    194: 
                    195:        /*
                    196:         * Initialize fields in the structure
                    197:         */
                    198:        policy->policy_id = policy_id;
                    199:        policy->priority_mask_length = priority_mask_length;
                    200:        policy->priority_mask = *priority_mask;
                    201:        /*** ??? should something more dynamic be done here for mask? ***/
                    202:        policy->sched_attributes_size = sizeof (mk_sp_attribute_struct_t);
                    203:        policy->sched_info_size = sizeof (mk_sp_info_struct_t);
                    204: 
                    205:        /*
                    206:         * Initialize table that maps computed priority values into
                    207:         * allocated metapriority values.
                    208:         */
                    209: 
                    210:        /* Find first metapriority value allocated to this policy */
                    211:        first_metapri = MAXPRI - ffsbit(priority_mask->bitmap);
                    212:        /*** ??? how to test for no set bits? ***/
                    213: 
                    214:        /* Map computed priorities higher than this to first metapriority */
                    215:        for (i = MAXPRI; i > first_metapri; i--)
                    216:                convert_pri[i] = first_metapri;
                    217:  
                    218:        /* For each remaining computed priority value... */
                    219:        for (i = first_metapri; i >= 0; i--) {
                    220:                /* ... is it a metapriority value assigned to this policy ?*/
                    221:                if (testbit(MAXPRI - i, priority_mask->bitmap)) {
                    222:                        /* Yes; just use it */
                    223:                        convert_pri[i] = i;
                    224:                        last_metapri = i;
                    225:                }
                    226:                else {
                    227:                        /* No, bump it up to the last value assigned */
                    228:                        convert_pri[i] = last_metapri;
                    229:                }
                    230:        }
                    231: 
                    232:        /* Remember lowest "normal" priority available to this policy */
                    233:        lpri = convert_pri[LPRI];
                    234: 
                    235:        min_quantum_ms = (1000 / hz) * min_quantum;
                    236: 
                    237: #if 0
                    238:        /* Initialize operation entries in "jump table" */
                    239:        /***
                    240:         *** ??? These must be done elsewhere.  Otherwise, there is a
                    241:         *** circularity: How does the framework find this init operation?
                    242:         ***/
                    243:        policy->sp_ops = mk_sp_ops;
                    244: 
                    245:        policy->sp_ops.sp_enable_processor_set = sp_mk_enable_processor_set;
                    246:        policy->sp_ops.sp_disable_processor_set = sp_mk_disable_processor_set;
                    247:        policy->sp_ops.sp_enable_processor = sp_mk_enable_processor;
                    248:        policy->sp_ops.sp_disable_processor = sp_mk_disable_processor;
                    249:        policy->sp_ops.sp_thread_unblock = sp_mk_thread_unblock;
                    250:        policy->sp_ops.sp_thread_done = sp_mk_thread_done;
                    251:        policy->sp_ops.sp_thread_begin = sp_mk_thread_begin;
                    252:        policy->sp_ops.sp_thread_attach = sp_mk_thread_attach;
                    253:        policy->sp_ops.sp_thread_detach = sp_mk_thread_detach;
                    254:        policy->sp_ops.sp_thread_processor = sp_mk_thread_processor;
                    255:        policy->sp_ops.sp_thread_processor_set = sp_mk_thread_processor_set;
                    256:        policy->sp_ops.sp_thread_set = sp_mk_thread_set;
                    257:        policy->sp_ops.sp_thread_get = sp_mk_thread_get;
                    258:        policy->sp_ops.sp_db_print_sched_stats = sp_mk_db_print_sched_stats;
                    259: #endif
                    260: 
                    261:        return(SF_SUCCESS);
                    262: }
                    263: 
                    264: sf_return_t
                    265: _mk_sp_enable_processor_set(
                    266:        sf_object_t                     policy,
                    267:        processor_set_t         processor_set)
                    268: {
                    269:        kern_return_t           result;
                    270: 
                    271:        counter(c_mk_sp_enable_processor_set++);
                    272: 
                    273:        result = processor_set_policy_enable(processor_set, policy->policy_id);
                    274:        assert(result == KERN_SUCCESS);
                    275: 
                    276:        return(SF_SUCCESS);
                    277: }
                    278: 
                    279: sf_return_t
                    280: _mk_sp_disable_processor_set(
                    281:        sf_object_t                     policy,
                    282:        processor_set_t         processor_set)
                    283: {
                    284:        kern_return_t           result;
                    285: 
                    286:        counter(c_mk_sp_disable_processor_set++);
                    287: 
                    288:        result = processor_set_policy_disable(
                    289:                                                                processor_set, policy->policy_id, TRUE);
                    290:        assert(result == KERN_SUCCESS);
                    291: 
                    292:        return(SF_SUCCESS);
                    293: }
                    294: 
                    295: sf_return_t
                    296: _mk_sp_enable_processor(
                    297:        sf_object_t             policy,
                    298:        processor_t             processor)
                    299: {
                    300:        counter(c_mk_sp_enable_processor++);
                    301: 
                    302:        panic("not yet implemented???");
                    303: 
                    304:        return(SF_FAILURE);
                    305: }
                    306: 
                    307: sf_return_t
                    308: _mk_sp_disable_processor(
                    309:        sf_object_t             policy,
                    310:        processor_t             processor)
                    311: {
                    312:        counter(c_mk_sp_disable_processor++);
                    313: 
                    314:        panic("not yet implemented???");
                    315: 
                    316:        return(SF_FAILURE);
                    317: }
                    318: 
                    319: sf_return_t
                    320: _mk_sp_thread_update_mpri(
                    321:        sf_object_t                     policy,
                    322:        sched_thread_t          thread)
                    323: {
                    324:        mk_sp_info_t            sp_info;
                    325: 
                    326:        counter(c_mk_sp_thread_update_mpri++);
                    327: 
                    328:        /* get pointer to scheduling policy-specific data */
                    329:        assert(thread->sp_info != SP_INFO_NULL);
                    330:        sp_info = (mk_sp_info_t)thread->sp_info;
                    331: 
                    332:        if (sp_info->sched_stamp != sched_tick)
                    333:                update_priority(thread);
                    334: 
                    335:        return(SF_SUCCESS);
                    336: }
                    337: 
                    338: sf_return_t
                    339: _mk_sp_thread_unblock(
                    340:        sf_object_t                     policy,
                    341:        sched_thread_t          thread)
                    342: {
                    343:        mk_sp_info_t            sp_info;
                    344: 
                    345:        counter(c_mk_sp_thread_unblock++);
                    346: 
                    347:        /* get pointer to scheduling policy-specific data */
                    348:        assert(thread->sp_info != SP_INFO_NULL);
                    349:        sp_info = (mk_sp_info_t)thread->sp_info;
                    350: 
                    351:        counter(sp_info->c_mk_sp_thread_unblock++);
                    352: 
                    353:        /*
                    354:         * The following assert is removed because we're hacking the
                    355:         * MK_SP_BLOCKED bit and removing it early to get SMP to work
                    356:         * with this gosh darned scheduler.  The whole danged thing is lousy and 
                    357:         * needs to be removed.  Hopefully for now, no one tries to
                    358:         * unblock a really runnable guy - HACKALERT!!!
                    359:         */             
                    360:                                
                    361:        /* check for legal thread states */
                    362: #if 0
                    363:        assert(sp_info->th_state == MK_SP_BLOCKED ||
                    364:               sp_info->th_state == MK_SP_ATTACHED); /* ??? work to remove*/
                    365: #endif
                    366:        /* indicate thread is now runnable */
                    367:        sp_info->th_state = MK_SP_RUNNABLE;
                    368: 
                    369:        /* place thread at end of appropriate run queue */
                    370:        thread_setrun(thread, TRUE, TAIL_Q);
                    371: 
                    372:        return(SF_SUCCESS);
                    373: }
                    374: 
                    375: sf_return_t
                    376: _mk_sp_thread_done(
                    377:        sf_object_t                     policy,
                    378:        sched_thread_t          old_thread)
                    379: {
                    380:        processor_t                     myprocessor = cpu_to_processor(cpu_number());
                    381:        mk_sp_info_t            sp_info;
                    382: 
                    383:        counter(c_mk_sp_thread_done++);
                    384: 
                    385:        /*
                    386:         * A running thread is being taken off a processor:
                    387:         *
                    388:         *   - update the thread's `unconsumed_quantum' field
                    389:         *   - update the thread's state field
                    390:         */
                    391: 
                    392:        /* get pointer to scheduling policy-specific data */
                    393:        assert(old_thread->sp_info != SP_INFO_NULL);
                    394:        sp_info = (mk_sp_info_t)old_thread->sp_info;
                    395: 
                    396:        counter(sp_info->c_mk_sp_thread_done++);
                    397:        assert((sp_info->c_mk_sp_thread_done
                    398:                   == sp_info->c_mk_sp_thread_begin + 1) ||
                    399:               (sp_info->c_mk_sp_thread_done
                    400:                   == sp_info->c_mk_sp_thread_begin));
                    401: 
                    402:        sp_info->unconsumed_quantum = myprocessor->quantum;
                    403: 
                    404:        /* check thread's current state */
                    405:        assert(mk_sp_first_thread || (sp_info->th_state & MK_SP_RUNNABLE));
                    406: #ifdef MACH_ASSERT
                    407:        mk_sp_first_thread = FALSE;
                    408: #endif /* MACH_ASSERT */
                    409: 
                    410:        /* update thread's state field based on reason for stopping now */
                    411:        /*** ??? is this condition correct? should it be more selective? ***/
                    412:        /*** ??? if ((old_thread->reason != AST_NONE) ||
                    413:            (old_thread->wait_event != NO_EVENT)) { ***/
                    414:        if (old_thread->state & TH_WAIT) {
                    415:                sp_info->th_state = MK_SP_BLOCKED;
                    416:        }
                    417: 
                    418:        return(SF_SUCCESS);
                    419: }
                    420: 
                    421: sf_return_t
                    422: _mk_sp_thread_begin(
                    423:        sf_object_t                     policy,
                    424:        sched_thread_t          thread)
                    425: {
                    426: 
                    427:        processor_t                     myprocessor = cpu_to_processor(cpu_number());
                    428:        processor_set_t         pset;
                    429:        mk_sp_info_t            sp_info;
                    430: 
                    431:        counter(c_mk_sp_thread_begin++);
                    432: 
                    433:        pset = myprocessor->processor_set;
                    434:        /*
                    435:         * The designated thread is about to begin execution:
                    436:         *
                    437:         *   - update the processor's `quantum' field
                    438:         */
                    439: 
                    440:        /* get pointer to scheduling policy-specific data */
                    441:        assert(thread->sp_info != SP_INFO_NULL);
                    442:        sp_info = (mk_sp_info_t)thread->sp_info;
                    443: 
                    444:        counter(sp_info->c_mk_sp_thread_begin++);
                    445:        assert((sp_info->c_mk_sp_thread_done
                    446:                   == sp_info->c_mk_sp_thread_begin) ||
                    447:               (sp_info->c_mk_sp_thread_done + 1
                    448:                   == sp_info->c_mk_sp_thread_begin));
                    449: 
                    450:        /* check for legal thread state */
                    451:        assert(sp_info->th_state == MK_SP_RUNNABLE);
                    452: 
                    453:        if (thread->policy & (POLICY_RR|POLICY_FIFO))
                    454:                myprocessor->quantum = sp_info->unconsumed_quantum;
                    455:        else
                    456:                myprocessor->quantum = (thread->bound_processor ?
                    457:                                                                                min_quantum : pset->set_quantum);
                    458: 
                    459:        return(SF_SUCCESS);
                    460: }
                    461: 
                    462: sf_return_t
                    463: _mk_sp_thread_dispatch(
                    464:        sf_object_t                     policy,
                    465:        sched_thread_t          old_thread)
                    466: {
                    467:        mk_sp_info_t    sp_info;
                    468: 
                    469:        counter(c_mk_sp_thread_dispatch++);
                    470: 
                    471:        /* get pointer to scheduling policy-specific data */
                    472:        assert(old_thread->sp_info != SP_INFO_NULL);
                    473:        sp_info = (mk_sp_info_t)old_thread->sp_info;
                    474: 
                    475:        counter(sp_info->c_mk_sp_thread_dispatch++);
                    476: 
                    477:        if (sp_info->th_state & MK_SP_RUNNABLE) {
                    478:                if (old_thread->reason & AST_QUANTUM) {
                    479:                        thread_setrun(old_thread, FALSE, TAIL_Q);
                    480:                        sp_info->unconsumed_quantum = sp_info->sched_data;
                    481:                }
                    482:                else
                    483:                        thread_setrun(old_thread, FALSE, HEAD_Q);
                    484:        }
                    485: 
                    486:        if (sp_info->th_state & MK_SP_ATTACHED) {
                    487:                /* indicate thread is now runnable */
                    488:                sp_info->th_state = MK_SP_RUNNABLE;
                    489: 
                    490:                /* place thread at end of appropriate run queue */
                    491:                thread_setrun(old_thread, FALSE, TAIL_Q);
                    492:        }
                    493: 
                    494:        return(SF_SUCCESS);
                    495: }
                    496: 
                    497: /*
                    498:  * Thread must already be locked.
                    499:  */
                    500: sf_return_t
                    501: _mk_sp_thread_attach(
                    502:        sf_object_t                     policy,
                    503:        sched_thread_t          thread)
                    504: {
                    505:        mk_sp_info_t            sp_info;
                    506: 
                    507:        counter(c_mk_sp_thread_attach++);
                    508: 
                    509:        /* Make sure there is a place for policy-specific state */
                    510:        assert(thread->sp_info != SP_INFO_NULL);
                    511: 
                    512:        sp_info = (mk_sp_info_t)thread->sp_info;
                    513:        sp_info->th_state = MK_SP_ATTACHED;
                    514:        /*** ??? Do these need to be done here? ***/
                    515:        /*** ??? If so, could fill from template for speed -- maybe ***/
                    516:        sp_info->priority = MINPRI;             /*** ??? ***/
                    517:        sp_info->max_priority = BASEPRI_USER;
                    518:        /*** ??? sp_info->sched_pri =
                    519:                        (later - compute_priority); (for now, at least) ***/
                    520:        sp_info->sched_data = 0;
                    521:        sp_info->policy = policy->policy_id;    /*** ??? ***/
                    522:        sp_info->depress_priority = -1;
                    523:        sp_info->cpu_usage = 0;
                    524:        sp_info->sched_usage = 0;
                    525:        sp_info->sched_stamp = 0;               /*** ??? ***/
                    526:        sp_info->unconsumed_quantum = 0;        /*** ??? ***/
                    527: 
                    528: #ifdef MACH_ASSERT
                    529:        sp_info->c_mk_sp_thread_attach = 1;
                    530:        sp_info->c_mk_sp_thread_detach = 0;
                    531:        sp_info->c_mk_sp_thread_begin = 0;
                    532:        sp_info->c_mk_sp_thread_done = 0;
                    533:        sp_info->c_mk_sp_thread_dispatch = 0;
                    534:        sp_info->c_mk_sp_thread_unblock = 0;
                    535:        sp_info->c_mk_sp_thread_set = 0;
                    536:        sp_info->c_mk_sp_thread_get = 0;
                    537: #endif /* MACH_ASSERT */
                    538: 
                    539:        /* Reflect this policy in thread data structure */
                    540:        thread->policy = policy->policy_id;
                    541: 
                    542:        return(SF_SUCCESS);
                    543: }
                    544: 
                    545: /*
                    546:  * Check to make sure that thread is removed from run
                    547:  * queues and active execution; and clean up the
                    548:  * policy-specific data structure for thread.
                    549:  *
                    550:  * Thread must already be locked.
                    551:  */
                    552: sf_return_t
                    553: _mk_sp_thread_detach(
                    554:        sf_object_t                     policy,
                    555:        sched_thread_t          thread)
                    556: {
                    557:        mk_sp_info_t            sp_info;
                    558:        struct run_queue        *rq;
                    559: 
                    560:        assert(thread->policy == policy->policy_id);
                    561: 
                    562:        counter(c_mk_sp_thread_detach++);
                    563:        /* get pointer to scheduling policy-specific data */
                    564:        assert(thread->sp_info != SP_INFO_NULL);
                    565:        sp_info = (mk_sp_info_t)thread->sp_info;
                    566: 
                    567:        counter(sp_info->c_mk_sp_thread_detach++);
                    568: 
                    569:        /* make sure that the thread has stopped executing */
                    570:        /*** ??? look at machine's version of RUN bit, too? ***/
                    571:        /***
                    572:         *** Fix for SMP case.
                    573:         ***/
                    574: 
                    575:        /* make sure that the thread is no longer on any run queue */
                    576:        if (thread->runq != RUN_QUEUE_NULL) {
                    577:                rq = rem_runq(thread);
                    578:                if (rq == RUN_QUEUE_NULL) {
                    579:                        panic("mk_sp_thread_detach: missed thread");
                    580:                }
                    581:        }
                    582: 
                    583:        /* (optionally) clear policy-specific data structure for the thread */
                    584: 
                    585:        if (sp_info->depress_priority >= 0) {
                    586:                sp_info->priority = sp_info->depress_priority;
                    587:                sp_info->depress_priority = -1;
                    588:                if (thread_call_cancel(&thread->depress_timer))
                    589:                        thread_call_enter(&thread->depress_timer);
                    590:        }
                    591: 
                    592:        /* clear the thread's policy field */
                    593:        thread->policy = POLICY_NULL;
                    594: 
                    595:        return(SF_SUCCESS);
                    596: }
                    597: 
                    598: sf_return_t
                    599: _mk_sp_thread_processor(
                    600:        sf_object_t                     policy,
                    601:        sched_thread_t          *thread,
                    602:        processor_t                     processor)
                    603: {
                    604:        counter(c_mk_sp_thread_processor++);
                    605: 
                    606:        panic("not yet implemented???");
                    607: 
                    608:        return(SF_FAILURE);
                    609: }
                    610: 
                    611: sf_return_t
                    612: _mk_sp_thread_processor_set(
                    613:        sf_object_t                     policy,
                    614:        sched_thread_t          thread,
                    615:        processor_set_t         processor_set)
                    616: {
                    617:        counter(c_mk_sp_thread_processor_set++);
                    618: 
                    619:        pset_add_thread(processor_set, thread);
                    620: 
                    621:        return(SF_SUCCESS);
                    622: }
                    623: 
                    624: sf_return_t
                    625: _mk_sp_thread_set(
                    626:        sf_object_t                     policy,
                    627:        sched_thread_t          thread,
                    628:        sp_attributes_t         policy_attributes)
                    629: {
                    630:        mk_sp_info_t            sp_info;
                    631:        mk_sp_attributes_t      attributes;
                    632: 
                    633:        counter(c_mk_sp_thread_set++);
                    634: 
                    635:        /* check that attributes are for this policy */
                    636:        assert(policy_attributes->policy_id == policy->policy_id);
                    637: 
                    638:        attributes = (mk_sp_attributes_t)policy_attributes;
                    639: 
                    640:        /* get pointer to scheduling policy-specific data */
                    641:        assert(thread->sp_info != SP_INFO_NULL);
                    642:        sp_info = (mk_sp_info_t)thread->sp_info;
                    643: 
                    644:        counter(sp_info->c_mk_sp_thread_set++);
                    645: 
                    646:        /* update scheduling parameters */
                    647:        sp_info->priority = attributes->priority;
                    648:        sp_info->max_priority = attributes->max_priority;
                    649:        sp_info->sched_data = attributes->sched_data;
                    650:        sp_info->unconsumed_quantum = attributes->unconsumed_quantum;
                    651: 
                    652:        /*
                    653:         * No check is needed against the pset limit.  If the task could raise
                    654:         * its priority above the limit, then it must have had permisssion.
                    655:         */
                    656: 
                    657:        /*
                    658:         * Determine thread's state.  (It may be an "older" thread
                    659:         * that has just been associated with this policy.)
                    660:         */
                    661:        if (thread->state & TH_WAIT) {
                    662:            sp_info->th_state = MK_SP_BLOCKED;
                    663:        }
                    664: 
                    665:        /* recompute priority */
                    666:        sp_info->sched_stamp = sched_tick;
                    667:        compute_priority(thread, TRUE);
                    668: 
                    669:        return(SF_SUCCESS);
                    670: }
                    671: 
                    672: sf_return_t
                    673: _mk_sp_thread_get(
                    674:        sf_object_t                             policy,
                    675:        sched_thread_t                  thread,
                    676:        sp_attributes_t                 policy_attributes,
                    677:        sp_attributes_size_t    size)
                    678:        /*
                    679:         * Assumes that thread is locked.
                    680:         */
                    681:        /***
                    682:         *** ??? Does it assume `splsched()'?
                    683:         ***/
                    684: {
                    685:        mk_sp_info_t            sp_info;
                    686:        mk_sp_attributes_t      attributes;
                    687: 
                    688:        counter(c_mk_sp_thread_get++);
                    689: 
                    690:        /* check size of attribute structure provided by caller */
                    691:        if (policy->sched_attributes_size > size)
                    692:                return(SF_FAILURE);
                    693: 
                    694:        attributes = (mk_sp_attributes_t)policy_attributes;
                    695: 
                    696: 
                    697:        /* get pointer to scheduling policy-specific data */
                    698:        assert(thread->sp_info != SP_INFO_NULL);
                    699:        sp_info = (mk_sp_info_t)thread->sp_info;
                    700: 
                    701:        counter(sp_info->c_mk_sp_thread_get++);
                    702: 
                    703:        /* copy scheduling attributes */
                    704:        attributes->policy_id = policy->policy_id;
                    705:        attributes->priority = sp_info->priority;
                    706:        attributes->max_priority = sp_info->max_priority;
                    707:        attributes->sched_data = sp_info->sched_data;
                    708:        attributes->unconsumed_quantum = sp_info->unconsumed_quantum;
                    709: 
                    710:        return(SF_SUCCESS);
                    711: }
                    712: 
                    713: int
                    714: _mk_sp_db_print_sched_stats(
                    715:        sf_object_t                     policy,
                    716:        sched_thread_t          thread)
                    717: {
                    718:        mk_sp_info_t            sp_info;
                    719: 
                    720:        counter(c_mk_sp_db_print_sched_stats++);
                    721: 
                    722:        /* get pointer to scheduling policy-specific data */
                    723:        assert(thread->sp_info != SP_INFO_NULL);
                    724:        sp_info = (mk_sp_info_t)thread->sp_info;
                    725: 
                    726:        /* print one field -- `sched_pri' */
                    727:        return (thread->sched_pri);
                    728: }
                    729: 
                    730: /*
                    731:  *     thread_priority:
                    732:  *
                    733:  *     Set priority (and possibly max priority) for thread.
                    734:  */
                    735: kern_return_t
                    736: thread_priority(
                    737:        thread_act_t            thr_act,
                    738:        int                     priority,
                    739:        boolean_t               set_max)
                    740: {
                    741:        kern_return_t           result;
                    742:        thread_t                thread;
                    743: 
                    744:        if (thr_act == THR_ACT_NULL)
                    745:                return (KERN_INVALID_ARGUMENT);
                    746: 
                    747:        thread = act_lock_thread(thr_act);
                    748:        if (thread == THREAD_NULL || invalid_pri(priority)) {
                    749:                act_unlock_thread(thr_act);
                    750:                return (KERN_INVALID_ARGUMENT);
                    751:        }
                    752: 
                    753:        result = thread_priority_locked(thread, priority, set_max);
                    754:        act_unlock_thread(thr_act);
                    755: 
                    756:        return (result);
                    757: }
                    758: 
                    759: /*
                    760:  *     thread_priority_locked:
                    761:  *
                    762:  *     Kernel-internal work function for thread_priority().  Called
                    763:  *     with thread "properly locked" to ensure synchrony with RPC
                    764:  *     (see act_lock_thread()).
                    765:  */
                    766: kern_return_t
                    767: thread_priority_locked(
                    768:        thread_t                thread,
                    769:        int                     priority,
                    770:        boolean_t               set_max)
                    771: {
                    772:        kern_return_t           result = KERN_SUCCESS;
                    773:        mk_sp_info_t            sched_info;
                    774:        spl_t                   s;
                    775: 
                    776:        s = splsched();
                    777:        thread_lock(thread);
                    778: 
                    779:        /* get pointer to scheduling policy-specific data */
                    780:        assert(thread->sp_info != SP_INFO_NULL);
                    781:        sched_info = (mk_sp_info_t)thread->sp_info;
                    782: 
                    783:        /*
                    784:         *      Check for violation of max priority
                    785:         */
                    786:        if (priority > sched_info->max_priority)
                    787:                result = KERN_FAILURE;
                    788:        else {
                    789:                /*
                    790:                 *      Set priorities.  If a depression is in progress,
                    791:                 *      change the priority to restore.
                    792:                 */
                    793:                if (sched_info->depress_priority >= 0) {
                    794:                        sched_info->depress_priority = priority;
                    795:                }
                    796:                else {
                    797:                        sched_info->priority = priority;
                    798:                        compute_priority(thread, TRUE);
                    799: 
                    800:                        /*
                    801:                         * If the current thread has changed its
                    802:                         * priority let the ast code decide whether
                    803:                         * a different thread should run.
                    804:                         */
                    805:                        if (thread == current_thread())
                    806:                                ast_on(AST_BLOCK);
                    807:                }
                    808: 
                    809:                if (set_max)
                    810:                        sched_info->max_priority = priority;
                    811:        }
                    812: 
                    813:        thread_unlock(thread);
                    814:        splx(s);
                    815: 
                    816:        return(result);
                    817: }
                    818: 
                    819: /*
                    820:  *     thread_set_own_priority:
                    821:  *
                    822:  *     Internal use only; sets the priority of the calling thread.
                    823:  *     Will adjust max_priority if necessary.
                    824:  */
                    825: void
                    826: thread_set_own_priority(
                    827:        int             priority)
                    828: {
                    829:        thread_t        thread = current_thread();
                    830:        mk_sp_info_t    sched_info;
                    831:        spl_t           s;
                    832: 
                    833:        s = splsched();
                    834:        thread_lock(thread);
                    835: 
                    836:        /* get pointer to scheduling policy-specific data */
                    837:        assert(thread->sp_info != SP_INFO_NULL);
                    838:        sched_info = (mk_sp_info_t)thread->sp_info;
                    839: 
                    840:        if (priority > sched_info->max_priority)
                    841:                sched_info->max_priority = priority;
                    842:        sched_info->priority = priority;
                    843:        compute_priority(thread, TRUE);
                    844: 
                    845:        thread_unlock(thread);
                    846:        splx(s);
                    847: }
                    848: 
                    849: /*
                    850:  *     thread_max_priority:
                    851:  *
                    852:  *     Reset the max priority for a thread.
                    853:  */
                    854: kern_return_t
                    855: thread_max_priority(
                    856:        thread_act_t    thr_act,
                    857:        processor_set_t pset,
                    858:        int             max_priority)
                    859: {
                    860:        thread_t        thread;
                    861:        kern_return_t   result = KERN_SUCCESS;
                    862: 
                    863:        if (thr_act == THR_ACT_NULL)
                    864:                return(KERN_INVALID_ARGUMENT);
                    865: 
                    866:        thread = act_lock_thread(thr_act);
                    867:        if (thread == THREAD_NULL || pset == PROCESSOR_SET_NULL ||
                    868:                        invalid_pri(max_priority)) {
                    869:                act_unlock_thread(thr_act);
                    870:                return(KERN_INVALID_ARGUMENT);
                    871:        }
                    872: 
                    873:        result = thread_max_priority_locked(thread, pset, max_priority);
                    874:        act_unlock_thread(thr_act);
                    875: 
                    876:        return (result);
                    877: }
                    878: 
                    879: /*
                    880:  *     thread_max_priority_locked:
                    881:  *
                    882:  *     Work function for thread_max_priority.
                    883:  *
                    884:  *     Called with all RPC-related locks held for thread (see
                    885:  *     act_lock_thread()).
                    886:  */
                    887: kern_return_t
                    888: thread_max_priority_locked(
                    889:        thread_t        thread,
                    890:        processor_set_t pset,
                    891:        int             max_priority)
                    892: {
                    893:        kern_return_t   result = KERN_SUCCESS;
                    894:        mk_sp_info_t    sched_info;
                    895:        spl_t           s;
                    896: 
                    897:        s = splsched();
                    898:        thread_lock(thread);
                    899: 
                    900:        /* get pointer to scheduling policy-specific data */
                    901:        assert(thread->sp_info != SP_INFO_NULL);
                    902:        sched_info = (mk_sp_info_t)thread->sp_info;
                    903: 
                    904: #if    MACH_HOST
                    905:        /*
                    906:         *      Check for wrong processor set.
                    907:         */
                    908:        if (pset != thread->processor_set)
                    909:                result = KERN_FAILURE;
                    910:        else {
                    911: #endif /* MACH_HOST */
                    912:                sched_info->max_priority = max_priority;
                    913: 
                    914:                /*
                    915:                 *      Reset priority if it violates new max priority
                    916:                 */
                    917:                if (max_priority < sched_info->priority) {
                    918:                        sched_info->priority = max_priority;
                    919: 
                    920:                        compute_priority(thread, TRUE);
                    921:                }
                    922:                else if (sched_info->depress_priority >= 0 &&
                    923:                                max_priority < sched_info->depress_priority)
                    924:                        sched_info->depress_priority = max_priority;
                    925: #if    MACH_HOST
                    926:        }
                    927: #endif /* MACH_HOST */
                    928: 
                    929:        thread_unlock(thread);
                    930:        splx(s);
                    931: 
                    932:        return(result);
                    933: }
                    934: 
                    935: /*
                    936:  *     thread_policy_common:
                    937:  *
                    938:  *     Set scheduling policy for thread. If pset == PROCESSOR_SET_NULL,
                    939:  *     policy will be checked to make sure it is enabled.
                    940:  */
                    941: kern_return_t
                    942: thread_policy_common(
                    943:        thread_t        thread,
                    944:        int             policy,
                    945:        int             data,
                    946:        processor_set_t pset)
                    947: {
                    948:        kern_return_t   result = KERN_SUCCESS;
                    949:        mk_sp_info_t    sched_info;
                    950:        register int    temp;
                    951:        spl_t           s;
                    952: 
                    953:        if (thread == THREAD_NULL || invalid_policy(policy))
                    954:                return(KERN_INVALID_ARGUMENT);
                    955: 
                    956:        s = splsched();
                    957:        thread_lock(thread);
                    958: 
                    959:        /* get pointer to scheduling policy-specific data */
                    960:        assert(thread->sp_info != SP_INFO_NULL);
                    961:        sched_info = (mk_sp_info_t)thread->sp_info;
                    962: 
                    963:        /*
                    964:         *      Check if changing policy.
                    965:         */
                    966:        if (policy == thread->policy) {
                    967:            /*
                    968:             *  Just changing data.  This is meaningless for
                    969:             *  timeshareing, quantum for fixed priority (but
                    970:             *  has no effect until current quantum runs out).
                    971:             */
                    972:            if (policy == POLICY_FIFO || policy == POLICY_RR) {
                    973:                temp = data * 1000;
                    974:                if (temp % tick)
                    975:                    temp += tick;
                    976:                sched_info->sched_data = temp/tick;
                    977:                sched_info->unconsumed_quantum = temp/tick;
                    978:            }
                    979:        }
                    980:        else {
                    981:            /*
                    982:             *  Changing policy.  Check if new policy is allowed.
                    983:             */
                    984:            if (pset == PROCESSOR_SET_NULL && 
                    985:                        (thread->processor_set->policies & policy) == 0) {
                    986:                result = KERN_FAILURE;
                    987:            }
                    988:            else {
                    989:                if (pset != thread->processor_set) {
                    990:                    result = KERN_FAILURE;
                    991:                }
                    992:                else {
                    993:                    /*
                    994:                     *  Changing policy.  Save data and calculate new
                    995:                     *  priority.
                    996:                     */
                    997:                    thread->policy = policy;
                    998:                    sched_info->policy = policy;
                    999:                    if (policy == POLICY_FIFO || policy == POLICY_RR) {
                   1000:                        temp = data * 1000;
                   1001:                        if (temp % tick)
                   1002:                            temp += tick;
                   1003:                        sched_info->sched_data = temp/tick;
                   1004:                        sched_info->unconsumed_quantum = temp/tick;
                   1005:                    }
                   1006:                    compute_priority(thread, TRUE);
                   1007:                }
                   1008:            }
                   1009:        }
                   1010: 
                   1011:        thread_unlock(thread);
                   1012:        splx(s);
                   1013: 
                   1014:        return(result);
                   1015: }
                   1016: 
                   1017: /*
                   1018:  *     thread_set_policy
                   1019:  *
                   1020:  *     Set scheduling policy and parameters, both base and limit, for 
                   1021:  *     the given thread. Policy can be any policy implemented by the
                   1022:  *     processor set, whether enabled or not. 
                   1023:  */
                   1024: kern_return_t
                   1025: thread_set_policy(
                   1026:        thread_act_t                    thr_act,
                   1027:        processor_set_t                 pset,
                   1028:        policy_t                        policy,
                   1029:        policy_base_t                   base,
                   1030:        mach_msg_type_number_t          base_count,
                   1031:        policy_limit_t                  limit,
                   1032:        mach_msg_type_number_t          limit_count)
                   1033: {
                   1034:        thread_t                        thread;
                   1035:        int                             max, bas, dat;
                   1036:        kern_return_t                   result = KERN_SUCCESS;
                   1037: 
                   1038:        if (thr_act == THR_ACT_NULL || pset == PROCESSOR_SET_NULL)
                   1039:                return (KERN_INVALID_ARGUMENT);
                   1040: 
                   1041:        thread = act_lock_thread(thr_act);
                   1042:        if (thread == THREAD_NULL) {
                   1043:                act_unlock_thread(thr_act);
                   1044:                return(KERN_INVALID_ARGUMENT);
                   1045:        }
                   1046: 
                   1047:        if (pset != thread->processor_set) {
                   1048:                act_unlock_thread(thr_act);
                   1049:                return(KERN_FAILURE);
                   1050:        }
                   1051: 
                   1052:        switch (policy) {
                   1053:        case POLICY_RR:
                   1054:        {
                   1055:                 policy_rr_base_t rr_base = (policy_rr_base_t) base;
                   1056:                 policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit;
                   1057: 
                   1058:                 if (base_count != POLICY_RR_BASE_COUNT ||
                   1059:                     limit_count != POLICY_RR_LIMIT_COUNT) {
                   1060:                         result = KERN_INVALID_ARGUMENT;
                   1061:                         break;
                   1062:                 }
                   1063:                dat = rr_base->quantum;
                   1064:                bas = rr_base->base_priority;
                   1065:                max = rr_limit->max_priority;
                   1066:                if (invalid_pri(bas) || invalid_pri(max)) {
                   1067:                        result = KERN_INVALID_ARGUMENT;
                   1068:                        break;
                   1069:                }
                   1070:                break;
                   1071:        }
                   1072: 
                   1073:        case POLICY_FIFO:
                   1074:        {
                   1075:                 policy_fifo_base_t fifo_base = (policy_fifo_base_t) base;
                   1076:                 policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit;
                   1077: 
                   1078:                 if (base_count != POLICY_FIFO_BASE_COUNT ||
                   1079:                     limit_count != POLICY_FIFO_LIMIT_COUNT) {
                   1080:                         result = KERN_INVALID_ARGUMENT;
                   1081:                         break;
                   1082:                 }
                   1083:                dat = 0;
                   1084:                bas = fifo_base->base_priority;
                   1085:                max = fifo_limit->max_priority;
                   1086:                if (invalid_pri(bas) || invalid_pri(max)) {
                   1087:                        result = KERN_INVALID_ARGUMENT;
                   1088:                         break;
                   1089:                 }
                   1090:                 break;
                   1091:        }
                   1092: 
                   1093:        case POLICY_TIMESHARE:
                   1094:         {
                   1095:                 policy_timeshare_base_t ts_base =
                   1096:                                         (policy_timeshare_base_t) base;
                   1097:                 policy_timeshare_limit_t ts_limit =
                   1098:                                         (policy_timeshare_limit_t) limit;
                   1099: 
                   1100:                 if (base_count != POLICY_TIMESHARE_BASE_COUNT ||
                   1101:                     limit_count != POLICY_TIMESHARE_LIMIT_COUNT) {
                   1102:                         result = KERN_INVALID_ARGUMENT;
                   1103:                         break;
                   1104:                 }
                   1105:                dat = 0;
                   1106:                bas = ts_base->base_priority;
                   1107:                max = ts_limit->max_priority;
                   1108:                if (invalid_pri(bas) || invalid_pri(max)) {
                   1109:                        result = KERN_INVALID_ARGUMENT;
                   1110:                         break;
                   1111:                 }
                   1112:                 break;
                   1113:        }
                   1114: 
                   1115:        default:
                   1116:                result = KERN_INVALID_POLICY;
                   1117:        }
                   1118: 
                   1119:        if (result != KERN_SUCCESS) {
                   1120:                act_unlock_thread(thr_act);
                   1121:                return(result);
                   1122:        }
                   1123: 
                   1124:        /*      
                   1125:         *      We've already checked the inputs for thread_max_priority,
                   1126:         *      so it's safe to ignore the return value.
                   1127:         */
                   1128:        (void) thread_max_priority_locked(thread, pset, max);   
                   1129:        result = thread_priority_locked(thread, bas, FALSE);
                   1130:        if (result == KERN_SUCCESS)
                   1131:                result = thread_policy_common(thread, policy, dat, pset);
                   1132:        act_unlock_thread(thr_act);
                   1133:        return(result);
                   1134: }
                   1135: 
                   1136: 
                   1137: /*
                   1138:  *     thread_policy
                   1139:  *
                   1140:  *     Set scheduling policy and parameters, both base and limit, for
                   1141:  *     the given thread. Policy must be a policy which is enabled for the
                   1142:  *     processor set. Change contained threads if requested. 
                   1143:  */
                   1144: kern_return_t
                   1145: thread_policy(
                   1146:        thread_act_t                    thr_act,
                   1147:         policy_t                       policy,
                   1148:         policy_base_t                  base,
                   1149:        mach_msg_type_number_t          count,
                   1150:         boolean_t                      set_limit)
                   1151: {
                   1152:        thread_t                        thread;
                   1153:         processor_set_t                        pset;
                   1154:        mk_sp_info_t                    sched_info;
                   1155:         kern_return_t                  result = KERN_SUCCESS;
                   1156:        policy_limit_t                  limit;
                   1157:         policy_rr_limit_data_t         rr_limit;
                   1158:         policy_fifo_limit_data_t       fifo_limit;
                   1159:         policy_timeshare_limit_data_t  ts_limit;
                   1160:        int                             limcount;
                   1161:        
                   1162:        if (thr_act == THR_ACT_NULL)
                   1163:                return (KERN_INVALID_ARGUMENT);
                   1164: 
                   1165:        thread = act_lock_thread(thr_act);
                   1166:        pset = thread->processor_set;
                   1167:        if (thread == THREAD_NULL || pset == PROCESSOR_SET_NULL) {
                   1168:                act_unlock_thread(thr_act);
                   1169:                return(KERN_INVALID_ARGUMENT);
                   1170:        }
                   1171: 
                   1172:        if (invalid_policy(policy) || (pset->policies & policy) == 0) {
                   1173:                act_unlock_thread(thr_act);
                   1174:                return(KERN_INVALID_POLICY);
                   1175:        }
                   1176: 
                   1177:        /* get pointer to scheduling policy-specific data */
                   1178:        assert(thread->sp_info != SP_INFO_NULL);
                   1179:        sched_info = (mk_sp_info_t)thread->sp_info;
                   1180: 
                   1181:        if (set_limit) {
                   1182:                /*
                   1183:                 *      Set scheduling limits to base priority.
                   1184:                 */
                   1185:                switch (policy) {
                   1186:                case POLICY_RR:
                   1187:                {
                   1188:                         policy_rr_base_t rr_base;
                   1189: 
                   1190:                         if (count != POLICY_RR_BASE_COUNT) {
                   1191:                                 result = KERN_INVALID_ARGUMENT;
                   1192:                                break;
                   1193:                        }
                   1194:                         limcount = POLICY_RR_LIMIT_COUNT;
                   1195:                         rr_base = (policy_rr_base_t) base;
                   1196:                         rr_limit.max_priority = rr_base->base_priority;
                   1197:                         limit = (policy_limit_t) &rr_limit;
                   1198:                        break;
                   1199:                }
                   1200: 
                   1201:                case POLICY_FIFO:
                   1202:                 {
                   1203:                                policy_fifo_base_t fifo_base;
                   1204: 
                   1205:                                if (count != POLICY_FIFO_BASE_COUNT) {
                   1206:                                 result = KERN_INVALID_ARGUMENT;
                   1207:                                break;
                   1208:                        }
                   1209:                                limcount = POLICY_FIFO_LIMIT_COUNT;
                   1210:                         fifo_base = (policy_fifo_base_t) base;
                   1211:                         fifo_limit.max_priority = fifo_base->base_priority;
                   1212:                         limit = (policy_limit_t) &fifo_limit;
                   1213:                        break;
                   1214:                }
                   1215: 
                   1216:                case POLICY_TIMESHARE:
                   1217:                 {
                   1218:                         policy_timeshare_base_t ts_base;
                   1219: 
                   1220:                         if (count != POLICY_TIMESHARE_BASE_COUNT) {
                   1221:                                 result = KERN_INVALID_ARGUMENT;
                   1222:                                break;
                   1223:                        }
                   1224:                         limcount = POLICY_TIMESHARE_LIMIT_COUNT;
                   1225:                         ts_base = (policy_timeshare_base_t) base;
                   1226:                         ts_limit.max_priority = ts_base->base_priority;
                   1227:                         limit = (policy_limit_t) &ts_limit;
                   1228:                        break;
                   1229:                }
                   1230: 
                   1231:                default:
                   1232:                        result = KERN_INVALID_POLICY;
                   1233:                        break;
                   1234:                }
                   1235: 
                   1236:        } else {
                   1237:                /*
                   1238:                 *      Use current scheduling limits. Ensure that the
                   1239:                 *      new base priority will not exceed current limits.
                   1240:                 */
                   1241:                 switch (policy) {
                   1242:                 case POLICY_RR:
                   1243:                 {
                   1244:                         policy_rr_base_t rr_base;
                   1245: 
                   1246:                         if (count != POLICY_RR_BASE_COUNT) {
                   1247:                                 result = KERN_INVALID_ARGUMENT;
                   1248:                                break;
                   1249:                        }
                   1250:                         limcount = POLICY_RR_LIMIT_COUNT;
                   1251:                         rr_base = (policy_rr_base_t) base;
                   1252:                        if (rr_base->base_priority >
                   1253:                                        sched_info->max_priority) {
                   1254:                                result = KERN_POLICY_LIMIT;
                   1255:                                break;
                   1256:                        }
                   1257:                         rr_limit.max_priority = sched_info->max_priority;
                   1258:                         limit = (policy_limit_t) &rr_limit;
                   1259:                         break;
                   1260:                }
                   1261: 
                   1262:                 case POLICY_FIFO:
                   1263:                 {
                   1264:                         policy_fifo_base_t fifo_base;
                   1265: 
                   1266:                         if (count != POLICY_FIFO_BASE_COUNT) {
                   1267:                                 result = KERN_INVALID_ARGUMENT;
                   1268:                                break;
                   1269:                        }
                   1270:                         limcount = POLICY_FIFO_LIMIT_COUNT;
                   1271:                         fifo_base = (policy_fifo_base_t) base;
                   1272:                        if (fifo_base->base_priority >
                   1273:                                        sched_info->max_priority) {
                   1274:                                result = KERN_POLICY_LIMIT;
                   1275:                                break;
                   1276:                        }
                   1277:                         fifo_limit.max_priority = sched_info->max_priority;
                   1278:                         limit = (policy_limit_t) &fifo_limit;
                   1279:                         break;
                   1280:                }
                   1281: 
                   1282:                 case POLICY_TIMESHARE:
                   1283:                 {
                   1284:                         policy_timeshare_base_t ts_base;
                   1285: 
                   1286:                         if (count != POLICY_TIMESHARE_BASE_COUNT) {
                   1287:                                 result = KERN_INVALID_ARGUMENT;
                   1288:                                break;
                   1289:                        }
                   1290:                         limcount = POLICY_TIMESHARE_LIMIT_COUNT;
                   1291:                         ts_base = (policy_timeshare_base_t) base;
                   1292:                        if (ts_base->base_priority >
                   1293:                                        sched_info->max_priority) {
                   1294:                                result = KERN_POLICY_LIMIT;
                   1295:                                break;
                   1296:                        }
                   1297:                         ts_limit.max_priority = sched_info->max_priority;
                   1298:                         limit = (policy_limit_t) &ts_limit;
                   1299:                         break;
                   1300:                }
                   1301: 
                   1302:                 default:
                   1303:                        result = KERN_INVALID_POLICY;
                   1304:                        break;
                   1305:                 }
                   1306: 
                   1307:        }
                   1308: 
                   1309:        act_unlock_thread(thr_act);
                   1310: 
                   1311:        if (result == KERN_SUCCESS)
                   1312:            result = thread_set_policy(thr_act, pset,
                   1313:                                         policy, base, count, limit, limcount);
                   1314: 
                   1315:        return(result);
                   1316: }
                   1317: 
                   1318: 
                   1319: /*
                   1320:  *     Define shifts for simulating (5/8)**n
                   1321:  */
                   1322: 
                   1323: shift_data_t   wait_shift[32] = {
                   1324:        {1,1},{1,3},{1,-3},{2,-7},{3,5},{3,-5},{4,-8},{5,7},
                   1325:        {5,-7},{6,-10},{7,10},{7,-9},{8,-11},{9,12},{9,-11},{10,-13},
                   1326:        {11,14},{11,-13},{12,-15},{13,17},{13,-15},{14,-17},{15,19},{16,18},
                   1327:        {16,-19},{17,22},{18,20},{18,-20},{19,26},{20,22},{20,-22},{21,-27}};
                   1328: 
                   1329: /*
                   1330:  *     do_priority_computation:
                   1331:  *
                   1332:  *     Calculate new priority for thread based on its base priority plus
                   1333:  *     accumulated usage.  PRI_SHIFT and PRI_SHIFT_2 convert from
                   1334:  *     usage to priorities.  SCHED_SHIFT converts for the scaling
                   1335:  *     of the sched_usage field by SCHED_SCALE.  This scaling comes
                   1336:  *     from the multiplication by sched_load (thread_timer_delta)
                   1337:  *     in sched.h.  sched_load is calculated as a scaled overload
                   1338:  *     factor in compute_mach_factor (mach_factor.c).
                   1339:  */
                   1340: #ifdef PRI_SHIFT_2
                   1341: #if    PRI_SHIFT_2 > 0
                   1342: #define do_priority_computation(sp_info, pri)                                          \
                   1343:        MACRO_BEGIN                                                                                                             \
                   1344:        (pri) = (sp_info)->priority             /* start with base priority */  \
                   1345:            - ((sp_info)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT))             \
                   1346:            - ((sp_info)->sched_usage >> (PRI_SHIFT_2 + SCHED_SHIFT));  \
                   1347:        if ((pri) < lpri) (pri) = lpri;                                                                 \
                   1348:        (pri) = convert_pri[(pri)];                                                                             \
                   1349:        MACRO_END
                   1350: #else  /* PRI_SHIFT_2 */
                   1351: #define do_priority_computation(sp_info, pri)                                          \
                   1352:        MACRO_BEGIN                                                                                                             \
                   1353:        (pri) = (sp_info)->priority             /* start with base priority */  \
                   1354:            - ((sp_info)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT))             \
                   1355:            + ((sp_info)->sched_usage >> (SCHED_SHIFT - PRI_SHIFT_2));  \
                   1356:        if ((pri) < lpri) (pri) = lpri;                                                                 \
                   1357:        (pri) = convert_pri[(pri)];                                                                             \
                   1358:        MACRO_END
                   1359: #endif /* PRI_SHIFT_2 */
                   1360: #else  /* defined(PRI_SHIFT_2) */
                   1361: #define do_priority_computation(sp_info, pri)                                          \
                   1362:        MACRO_BEGIN                                                                                                             \
                   1363:        (pri) = (sp_info)->priority             /* start with base priority */  \
                   1364:            - ((sp_info)->sched_usage >> (PRI_SHIFT + SCHED_SHIFT));    \
                   1365:        if ((pri) < lpri) (pri) = lpri;                                                                 \
                   1366:        (pri) = convert_pri[(pri)];                                                                             \
                   1367:        MACRO_END
                   1368: #endif /* defined(PRI_SHIFT_2) */
                   1369: 
                   1370: /*
                   1371:  *     compute_priority:
                   1372:  *
                   1373:  *     Compute the effective priority of the specified thread.
                   1374:  *     The effective priority computation is as follows:
                   1375:  *
                   1376:  *     Take the base priority for this thread and add
                   1377:  *     to it an increment derived from its cpu_usage.
                   1378:  *
                   1379:  *     The thread *must* be locked by the caller. 
                   1380:  */
                   1381: 
                   1382: void
                   1383: compute_priority(
                   1384:        register thread_t       thread,
                   1385:        boolean_t                       resched)
                   1386: {
                   1387:        mk_sp_info_t            sp_info = (mk_sp_info_t)thread->sp_info;
                   1388:        register int            pri;
                   1389: 
                   1390:        /* make sure policy-specific data are present */
                   1391:        assert(sp_info != SP_INFO_NULL);
                   1392: 
                   1393:        if (thread->policy == POLICY_TIMESHARE) {
                   1394:            do_priority_computation(sp_info, pri);
                   1395:            if (sp_info->depress_priority < 0)
                   1396:                        set_pri(thread, pri, resched);
                   1397:            else
                   1398:                        sp_info->depress_priority = pri;
                   1399:        }
                   1400:        else
                   1401:            set_pri(thread, sp_info->priority, resched);
                   1402: }
                   1403: 
                   1404: /*
                   1405:  *     compute_my_priority:
                   1406:  *
                   1407:  *     Version of compute priority for current thread or thread
                   1408:  *     being manipulated by scheduler (going on or off a runq).
                   1409:  *     Only used for priority updates.  Policy or priority changes
                   1410:  *     must call compute_priority above.  Caller must have thread
                   1411:  *     locked and know it is timesharing and not depressed.
                   1412:  */
                   1413: 
                   1414: void
                   1415: compute_my_priority(
                   1416:        register thread_t       thread)
                   1417: {
                   1418:        mk_sp_info_t    sp_info = (mk_sp_info_t)thread->sp_info;
                   1419:        register int    temp_pri;
                   1420: 
                   1421:        /* make sure policy-specific data are present */
                   1422:        assert(thread->sp_info != SP_INFO_NULL);
                   1423: 
                   1424:        do_priority_computation(sp_info,temp_pri);
                   1425:        assert(thread->runq == RUN_QUEUE_NULL);
                   1426:        thread->sched_pri = temp_pri;
                   1427: }
                   1428: 
                   1429: struct mk_sp_usage {
                   1430:        natural_t       cpu_delta, sched_delta;
                   1431:        natural_t       sched_tick, ticks;
                   1432:        natural_t       cpu_usage, sched_usage,
                   1433:                                aged_cpu, aged_sched;
                   1434:        thread_t        thread;
                   1435: } idled_info, loaded_info;
                   1436: 
                   1437: /*
                   1438:  *     update_priority
                   1439:  *
                   1440:  *     Cause the priority computation of a thread that has been 
                   1441:  *     sleeping or suspended to "catch up" with the system.  Thread
                   1442:  *     *MUST* be locked by caller.  If thread is running, then this
                   1443:  *     can only be called by the thread on itself.
                   1444:  */
                   1445: void
                   1446: update_priority(
                   1447:        register thread_t               thread)
                   1448: {
                   1449:        mk_sp_info_t                    sp_info = (mk_sp_info_t)thread->sp_info;
                   1450:        register unsigned int   ticks;
                   1451:        register shift_t                shiftp;
                   1452: 
                   1453:        /* make sure policy-specific data are present */
                   1454:        assert(sp_info != SP_INFO_NULL);
                   1455: 
                   1456:        ticks = sched_tick - sp_info->sched_stamp;
                   1457:        assert(ticks != 0);
                   1458: 
                   1459:        /*
                   1460:         *      If asleep for more than 30 seconds forget all
                   1461:         *      cpu_usage, else catch up on missed aging.
                   1462:         *      5/8 ** n is approximated by the two shifts
                   1463:         *      in the wait_shift array.
                   1464:         */
                   1465:        sp_info->sched_stamp += ticks;
                   1466:        thread_timer_delta(thread);
                   1467:        if (ticks >  30) {
                   1468:                sp_info->cpu_usage = 0;
                   1469:                sp_info->sched_usage = 0;
                   1470:        }
                   1471:        else {
                   1472:                struct mk_sp_usage *sp_usage;
                   1473: 
                   1474:                sp_info->cpu_usage += thread->cpu_delta;
                   1475:                sp_info->sched_usage += thread->sched_delta;
                   1476: 
                   1477:                if (thread->state & TH_IDLE)
                   1478:                        sp_usage = &idled_info;
                   1479:                else
                   1480:                if (thread == loaded_info.thread)
                   1481:                        sp_usage = &loaded_info;
                   1482:                else
                   1483:                        sp_usage = NULL;
                   1484: 
                   1485:                if (sp_usage != NULL) {
                   1486:                        sp_usage->cpu_delta = thread->cpu_delta;
                   1487:                        sp_usage->sched_delta = thread->sched_delta;
                   1488:                        sp_usage->sched_tick = sp_info->sched_stamp;
                   1489:                        sp_usage->ticks = ticks;
                   1490:                        sp_usage->cpu_usage = sp_info->cpu_usage;
                   1491:                        sp_usage->sched_usage = sp_info->sched_usage;
                   1492:                        sp_usage->thread = thread;
                   1493:                }
                   1494: 
                   1495:                shiftp = &wait_shift[ticks];
                   1496:                if (shiftp->shift2 > 0) {
                   1497:                    sp_info->cpu_usage =
                   1498:                                                (sp_info->cpu_usage >> shiftp->shift1) +
                   1499:                                                (sp_info->cpu_usage >> shiftp->shift2);
                   1500:                    sp_info->sched_usage =
                   1501:                                                (sp_info->sched_usage >> shiftp->shift1) +
                   1502:                                                (sp_info->sched_usage >> shiftp->shift2);
                   1503:                }
                   1504:                else {
                   1505:                    sp_info->cpu_usage =
                   1506:                                                (sp_info->cpu_usage >> shiftp->shift1) -
                   1507:                                                (sp_info->cpu_usage >> -(shiftp->shift2));
                   1508:                    sp_info->sched_usage =
                   1509:                                                (sp_info->sched_usage >> shiftp->shift1) -
                   1510:                                                (sp_info->sched_usage >> -(shiftp->shift2));
                   1511:                }
                   1512: 
                   1513:                if (sp_usage != NULL) {
                   1514:                        sp_usage->aged_cpu = sp_info->cpu_usage;
                   1515:                        sp_usage->aged_sched = sp_info->sched_usage;
                   1516:                }
                   1517:        }
                   1518:        thread->cpu_delta = 0;
                   1519:        thread->sched_delta = 0;
                   1520: 
                   1521:        /*
                   1522:         *      Recompute priority if appropriate.
                   1523:         */
                   1524:        if (    thread->policy == POLICY_TIMESHARE              &&
                   1525:                        sp_info->depress_priority < 0                   ) {
                   1526:                register int            new_pri;
                   1527:                run_queue_t                     runq;
                   1528: 
                   1529:                do_priority_computation(sp_info, new_pri);
                   1530:                runq = rem_runq(thread);
                   1531:                thread->sched_pri = new_pri;
                   1532:                if (runq != RUN_QUEUE_NULL)
                   1533:                        thread_setrun(thread, TRUE, TAIL_Q);
                   1534:        }
                   1535: }
                   1536: 
                   1537: /*
                   1538:  *     `mk_sp_swtch_pri()' attempts to context switch (logic in
                   1539:  *     thread_block no-ops the context switch if nothing would happen).
                   1540:  *     A boolean is returned that indicates whether there is anything
                   1541:  *     else runnable.
                   1542:  *
                   1543:  *     This boolean can be used by a thread waiting on a
                   1544:  *     lock or condition:  If FALSE is returned, the thread is justified
                   1545:  *     in becoming a resource hog by continuing to spin because there's
                   1546:  *     nothing else useful that the processor could do.  If TRUE is
                   1547:  *     returned, the thread should make one more check on the
                   1548:  *     lock and then be a good citizen and really suspend.
                   1549:  */
                   1550: 
                   1551: void
                   1552: _mk_sp_swtch_pri(
                   1553:        sf_object_t                     policy,
                   1554:        int                                     pri)
                   1555: {
                   1556:        register thread_t       self = current_thread();
                   1557: 
                   1558: #ifdef lint
                   1559:        pri++;
                   1560: #endif /* lint */
                   1561: 
                   1562:        counter(c_mk_sp_swtch_pri++);
                   1563:        /*
                   1564:         *      XXX need to think about depression duration.
                   1565:         *      XXX currently using min quantum.
                   1566:         */
                   1567:        _mk_sp_thread_depress_priority(policy, min_quantum_ms);
                   1568: 
                   1569:        counter(c_swtch_pri_block++);
                   1570:        thread_block((void (*)(void)) 0);
                   1571: 
                   1572:        _mk_sp_thread_depress_abort(policy, self);
                   1573: }
                   1574: 
                   1575: /*
                   1576:  *     thread_switch:
                   1577:  *
                   1578:  *     Context switch.  User may supply thread hint.
                   1579:  *
                   1580:  *     Fixed priority threads that call this get what they asked for
                   1581:  *     even if that violates priority order.
                   1582:  */
                   1583: kern_return_t
                   1584: _mk_sp_thread_switch(
                   1585:        sf_object_t                             policy,
                   1586:        thread_act_t                    hint_act,
                   1587:        int                                             option,
                   1588:        mach_msg_timeout_t              option_time)
                   1589: {
                   1590:     register thread_t          self = current_thread();
                   1591:     register processor_t       myprocessor;
                   1592:     mk_sp_info_t                       sp_info;
                   1593:        int                                             s;
                   1594: 
                   1595:     counter(c_mk_sp_thread_switch++);
                   1596: 
                   1597:     /*
                   1598:      * Process option.
                   1599:      */
                   1600:     switch (option) {
                   1601: 
                   1602:        case SWITCH_OPTION_NONE:
                   1603:            /*
                   1604:             *  Nothing to do.
                   1605:             */
                   1606:            break;
                   1607: 
                   1608:        case SWITCH_OPTION_DEPRESS:
                   1609:            /*
                   1610:             *  Depress priority for a given time.
                   1611:             */
                   1612:            _mk_sp_thread_depress_priority(policy, option_time);
                   1613:            break;
                   1614: 
                   1615:        case SWITCH_OPTION_WAIT:
                   1616:            assert_wait_timeout(option_time, THREAD_ABORTSAFE);
                   1617:            break;
                   1618: 
                   1619:        default:
                   1620:            return (KERN_INVALID_ARGUMENT);
                   1621:     }
                   1622:     
                   1623:     /*
                   1624:      * Check and use thr_act hint if appropriate.  It is not
                   1625:      *  appropriate to give a hint that shares the current shuttle.
                   1626:      *
                   1627:      *  JMM - Is it really appropriate to give a hint that isn't
                   1628:      *  the top activation for a thread?
                   1629:      */
                   1630:     if (hint_act->thread != self) {
                   1631:        register thread_t               thread = hint_act->thread;
                   1632:        
                   1633:                /*
                   1634:                 *      Check if the thread is in the right pset. Then
                   1635:                 *      pull it off its run queue.  If it
                   1636:                 *      doesn't come, then it's not eligible.
                   1637:                 */
                   1638:                if (thread) {
                   1639:                        s = splsched();
                   1640:                        thread_lock(thread);
                   1641: 
                   1642:                        if (    thread->processor_set == self->processor_set    &&
                   1643:                                        rem_runq(thread) != RUN_QUEUE_NULL                                      ) {
                   1644:                                /*
                   1645:                                 *      Hah, got it!!
                   1646:                                 */
                   1647:                                if (thread->policy & (POLICY_FIFO|POLICY_RR)) {
                   1648:                                        myprocessor = current_processor();
                   1649: 
                   1650:                                        assert(thread->sp_info != SP_INFO_NULL);
                   1651:                                        sp_info = (mk_sp_info_t)thread->sp_info;
                   1652: 
                   1653:                                        myprocessor->quantum = sp_info->unconsumed_quantum;
                   1654:                                        myprocessor->first_quantum = TRUE;
                   1655:                                }
                   1656:                                thread_unlock(thread);
                   1657:                                splx(s);
                   1658:                                act_unlock_thread(hint_act);
                   1659:                                
                   1660:                                counter(c_thread_switch_handoff++);
                   1661:                                thread_run((void(*)(void)) 0, thread);
                   1662: 
                   1663:                                goto out;
                   1664:                        }
                   1665: 
                   1666:                        thread_unlock(thread);
                   1667:                        splx(s);
                   1668:                }
                   1669: 
                   1670:                act_unlock_thread(hint_act);
                   1671:     }
                   1672: 
                   1673:     /*
                   1674:      * No handoff hint supplied, or hint was wrong.  Call thread_block() in
                   1675:      * hopes of running something else.  If nothing else is runnable,
                   1676:      * thread_block will detect this.  WARNING: thread_switch with no
                   1677:      * option will not do anything useful if the thread calling it is the
                   1678:      * highest priority thread (can easily happen with a collection
                   1679:      * of timesharing threads).
                   1680:      */
                   1681:        mp_disable_preemption();
                   1682:     myprocessor = current_processor();
                   1683:     if (       option != SWITCH_OPTION_NONE                                    ||
                   1684:                        myprocessor->processor_set->runq.count > 0              ||
                   1685:                        myprocessor->runq.count > 0                                                     ) {
                   1686:                myprocessor->first_quantum = FALSE;
                   1687:                mp_enable_preemption();
                   1688:          
                   1689:                counter(c_thread_switch_block++);
                   1690:                thread_block((void (*)(void)) 0);
                   1691:        }
                   1692:        else
                   1693:                mp_enable_preemption();
                   1694: 
                   1695: out:
                   1696:        if (option == SWITCH_OPTION_WAIT)
                   1697:                thread_cancel_timer();
                   1698:        else if (option == SWITCH_OPTION_DEPRESS)
                   1699:                _mk_sp_thread_depress_abort(policy, self);
                   1700: 
                   1701:     return (KERN_SUCCESS);
                   1702: }
                   1703: 
                   1704: /*
                   1705:  *     mk_sp_thread_depress_priority
                   1706:  *
                   1707:  *     Depress thread's priority to lowest possible for specified period.
                   1708:  *     Intended for use when thread wants a lock but doesn't know which
                   1709:  *     other thread is holding it.  As with thread_switch, fixed
                   1710:  *     priority threads get exactly what they asked for.  Users access
                   1711:  *     this by the SWITCH_OPTION_DEPRESS option to thread_switch.  A Time
                   1712:  *      of zero will result in no timeout being scheduled.
                   1713:  */
                   1714: void
                   1715: _mk_sp_thread_depress_priority(
                   1716:        sf_object_t                             policy,
                   1717:        mach_msg_timeout_t              interval)
                   1718: {
                   1719:        register thread_t               self = current_thread();
                   1720:     mk_sp_info_t                       sp_info;
                   1721:        AbsoluteTime                    deadline;
                   1722:        boolean_t                               release = FALSE;
                   1723:     spl_t                                      s;
                   1724: 
                   1725:     s = splsched();
                   1726:     thread_lock(self);
                   1727: 
                   1728:        if (self->policy == policy->policy_id) {
                   1729:                /* get pointer to scheduling policy-specific data */
                   1730:                assert(self->sp_info != SP_INFO_NULL);
                   1731:                sp_info = (mk_sp_info_t)self->sp_info;
                   1732: 
                   1733:                /*
                   1734:                 * If we haven't already saved the priority to be restored
                   1735:                 * (depress_priority), then save it.
                   1736:                 */
                   1737:                if (sp_info->depress_priority < 0)
                   1738:                        sp_info->depress_priority = sp_info->priority;
                   1739:                else if (thread_call_cancel(&self->depress_timer))
                   1740:                        release = TRUE;
                   1741: 
                   1742:                self->sched_pri = sp_info->priority = DEPRESSPRI;
                   1743: 
                   1744:                if (interval != 0) {
                   1745:                        clock_interval_to_deadline(
                   1746:                                                                interval, 1000*NSEC_PER_USEC, &deadline);
                   1747:                        thread_call_enter_delayed(&self->depress_timer, deadline);
                   1748:                        if (!release)
                   1749:                                self->ref_count++;
                   1750:                        else
                   1751:                                release = FALSE;
                   1752:                }
                   1753:        }
                   1754: 
                   1755:     thread_unlock(self);
                   1756:     splx(s);
                   1757: 
                   1758:        if (release)
                   1759:                thread_deallocate(self);
                   1760: }      
                   1761: 
                   1762: /*
                   1763:  *     mk_sp_thread_depress_timeout:
                   1764:  *
                   1765:  *     Timeout routine for priority depression.
                   1766:  */
                   1767: void
                   1768: _mk_sp_thread_depress_timeout(
                   1769:        sf_object_t                             policy,
                   1770:        register thread_t               thread)
                   1771: {
                   1772:     mk_sp_info_t                       sp_info;
                   1773:     spl_t                                      s;
                   1774: 
                   1775:     counter(c_mk_sp_thread_depress_timeout++);
                   1776: 
                   1777:     s = splsched();
                   1778:     thread_lock(thread);
                   1779:        if (thread->policy == policy->policy_id) {
                   1780:                /* get pointer to scheduling policy-specific data */
                   1781:                assert(thread->sp_info != SP_INFO_NULL);
                   1782:                sp_info = (mk_sp_info_t)thread->sp_info;
                   1783: 
                   1784:                /*
                   1785:                 *      If we lose a race with mk_sp_thread_depress_abort,
                   1786:                 *      then depress_priority might be -1.
                   1787:                 */
                   1788:                if (    sp_info->depress_priority >= 0                                          &&
                   1789:                                !thread_call_is_delayed(&thread->depress_timer, NULL)           ) {
                   1790:                        sp_info->priority = sp_info->depress_priority;
                   1791:                        sp_info->depress_priority = -1;
                   1792:                        compute_priority(thread, FALSE);
                   1793:                }
                   1794:                else
                   1795:                if (sp_info->depress_priority == -2) {
                   1796:                        /*
                   1797:                         * Thread was temporarily undepressed by thread_suspend, to
                   1798:                         * be redepressed in special_handler as it blocks.  We need to
                   1799:                         * prevent special_handler from redepressing it, since depression
                   1800:                         * has timed out:
                   1801:                         */
                   1802:                        sp_info->depress_priority = -1;
                   1803:                }
                   1804:        }
                   1805:        thread_unlock(thread);
                   1806:        splx(s);
                   1807: }
                   1808: 
                   1809: /*
                   1810:  *     mk_sp_thread_depress_abort:
                   1811:  *
                   1812:  *     Prematurely abort priority depression if there is one.
                   1813:  */
                   1814: kern_return_t
                   1815: _mk_sp_thread_depress_abort(
                   1816:        sf_object_t                             policy,
                   1817:        register thread_t               thread)
                   1818: {
                   1819:     mk_sp_info_t                       sp_info;
                   1820:     kern_return_t                      result = KERN_SUCCESS;
                   1821:        boolean_t                               release = FALSE;
                   1822:     spl_t                                      s;
                   1823: 
                   1824:     s = splsched();
                   1825:     thread_lock(thread);
                   1826: 
                   1827:        if (thread->policy == policy->policy_id) {
                   1828:                /* get pointer to scheduling policy-specific data */
                   1829:                assert(thread->sp_info != SP_INFO_NULL);
                   1830:                sp_info = (mk_sp_info_t)thread->sp_info;
                   1831: 
                   1832:                if (sp_info->depress_priority >= 0) {
                   1833:                        if (thread_call_cancel(&thread->depress_timer))
                   1834:                                release = TRUE;
                   1835:                        sp_info->priority = sp_info->depress_priority;
                   1836:                        sp_info->depress_priority = -1;
                   1837:                        compute_priority(thread, FALSE);
                   1838:                }
                   1839:                else
                   1840:                        result = KERN_NOT_DEPRESSED;
                   1841:        }
                   1842: 
                   1843:     thread_unlock(thread);
                   1844:     splx(s);
                   1845: 
                   1846:        if (release)
                   1847:                thread_deallocate(thread);
                   1848: 
                   1849:     return (result);
                   1850: }
                   1851: 
                   1852: /*
                   1853:  *     mk_sp_thread_runnable:
                   1854:  *
                   1855:  *     Return TRUE iff policy believes thread is runnable
                   1856:  */
                   1857: boolean_t
                   1858: _mk_sp_thread_runnable(
                   1859:        sf_object_t                     policy,
                   1860:        sched_thread_t          thread)
                   1861: {
                   1862:        mk_sp_info_t            sp_info;
                   1863: 
                   1864:        counter(c_mk_sp_thread_runnable++);
                   1865: 
                   1866:        /* get pointer to scheduling policy-specific data */
                   1867:        assert(thread->sp_info != SP_INFO_NULL);
                   1868:        sp_info = (mk_sp_info_t)thread->sp_info;
                   1869: 
                   1870:        counter(sp_info->c_mk_sp_thread_runnable++);
                   1871: 
                   1872:        return (sp_info->th_state == MK_SP_RUNNABLE);
                   1873: }
                   1874: 
                   1875: sf_return_t
                   1876: _mk_sp_alarm_expired(
                   1877:        sf_object_t                     policy,
                   1878:        long                            alarm_seqno,
                   1879:        kern_return_t           result,
                   1880:        int                                     alarm_type,
                   1881:        mach_timespec_t         wakeup_time,
                   1882:        void                            *alarm_data)
                   1883: {
                   1884:        counter(c_mk_sp_alarm_expired++);
                   1885: 
                   1886:        /* this should NEVER happen */
                   1887:        assert(0);
                   1888: 
                   1889:        return (SF_FAILURE);
                   1890: }
                   1891: 
                   1892: 
                   1893: void
                   1894: _mk_sp_thread_dump(
                   1895:        sched_thread_t          thread)         /* thread */
                   1896: {
                   1897:        mk_sp_info_t            sp_info;
                   1898:        int                     count;
                   1899: 
                   1900:        /* get pointer to scheduling policy-specific data */
                   1901:        assert(thread->sp_info != SP_INFO_NULL);
                   1902:        sp_info = (mk_sp_info_t)thread->sp_info;
                   1903: 
                   1904:        /* dump the data in a pretty format */
                   1905:        printf("\nthread shuttle(0x%x):\n", thread);
                   1906: 
                   1907:        printf("\tpolicy: ");
                   1908:        switch(thread->policy) {
                   1909:                case POLICY_TIMESHARE:
                   1910:                        printf("POLICY_TIMESHARE\n");
                   1911:                        break;
                   1912: 
                   1913:                case POLICY_RR:
                   1914:                        printf("POLICY_RR\n");
                   1915:                        break;
                   1916: 
                   1917:                case POLICY_FIFO:
                   1918:                        printf("POLICY_FIFO\n");
                   1919:                        break;
                   1920: 
                   1921:                default:
                   1922:                        printf("NOT an MK Standard Policy\n");
                   1923:                        return;
                   1924:        }
                   1925: 
                   1926:        printf("\tth_state: ");
                   1927:        if (sp_info->th_state == 0) {
                   1928:                printf("NULL");
                   1929:        }
                   1930:        else {
                   1931:                count = 0;
                   1932:                if (sp_info->th_state & MK_SP_ATTACHED) {
                   1933:                        printf("MK_SP_ATTACHED ");
                   1934:                        count++;
                   1935:                }
                   1936:                if (sp_info->th_state & MK_SP_RUNNABLE) {
                   1937:                        if (count > 0) printf(" | ");
                   1938:                        printf("MK_SP_RUNNABLE ");
                   1939:                        count++;
                   1940:                }
                   1941:                if (sp_info->th_state & MK_SP_BLOCKED) {
                   1942:                        if (count > 0) printf(" | ");
                   1943:                        printf("MK_SP_BLOCKED ");
                   1944:                        count++;
                   1945:                }
                   1946:        }
                   1947:        printf("\n");
                   1948: 
                   1949:        printf("\tpriority: %d\n", sp_info->priority);
                   1950:        printf("\tmax_priority: %d\n", sp_info->max_priority);
                   1951:        printf("\tsched_data: %d\n", sp_info->sched_data);
                   1952:        printf("\tdepress_priority: %d\n", sp_info->depress_priority);
                   1953:        printf("\tcpu_usage: %d\n", sp_info->cpu_usage);
                   1954:        printf("\tsched_usage: %d\n", sp_info->sched_usage);
                   1955:        printf("\tsched_stamp: %d\n", sp_info->sched_stamp);
                   1956:        printf("\tunconsumed_quantum: %d\n", sp_info->unconsumed_quantum);
                   1957:        printf("\tsched_pri: %d\n", thread->sched_pri);
                   1958: 
                   1959: #ifdef MACH_ASSERT
                   1960:        printf("\tc_mk_sp_thread_attach: %d\n",
                   1961:               sp_info->c_mk_sp_thread_attach);
                   1962:        printf("\tc_mk_sp_thread_detach: %d\n",
                   1963:               sp_info->c_mk_sp_thread_detach);
                   1964:        printf("\tc_mk_sp_thread_begin: %d\n",
                   1965:               sp_info->c_mk_sp_thread_begin);
                   1966:        printf("\tc_mk_sp_thread_done: %d\n",
                   1967:               sp_info->c_mk_sp_thread_done);
                   1968:        printf("\tc_mk_sp_thread_dispatch: %d\n",
                   1969:               sp_info->c_mk_sp_thread_dispatch);
                   1970:        printf("\tc_mk_sp_thread_unblock: %d\n",
                   1971:               sp_info->c_mk_sp_thread_unblock);
                   1972:        printf("\tc_mk_sp_thread_set: %d\n",
                   1973:               sp_info->c_mk_sp_thread_set);
                   1974:        printf("\tc_mk_sp_thread_get: %d\n",
                   1975:               sp_info->c_mk_sp_thread_get);
                   1976: #endif /* MACH_ASSERT */
                   1977: 
                   1978:        return;
                   1979: }

unix.superglobalmegacorp.com

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