Annotation of OSKit-Mach/kern/syscall_subr.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
                      4:  * Copyright (c) 1993,1994 The University of Utah and
                      5:  * the Computer Systems Laboratory (CSL).
                      6:  * All rights reserved.
                      7:  *
                      8:  * Permission to use, copy, modify and distribute this software and its
                      9:  * documentation is hereby granted, provided that both the copyright
                     10:  * notice and this permission notice appear in all copies of the
                     11:  * software, derivative works or modified versions, and any portions
                     12:  * thereof, and that both notices appear in supporting documentation.
                     13:  *
                     14:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
                     15:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
                     16:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
                     17:  * THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  [email protected]
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  */
                     29: 
                     30: #include <mach_fixpri.h>
                     31: #include <cpus.h>
                     32: 
                     33: #include <mach/boolean.h>
                     34: #include <mach/thread_switch.h>
                     35: #include <ipc/ipc_port.h>
                     36: #include <ipc/ipc_space.h>
                     37: #include <kern/counters.h>
                     38: #include <kern/ipc_kobject.h>
                     39: #include <kern/processor.h>
                     40: #include <kern/sched.h>
                     41: #include <kern/sched_prim.h>
                     42: #include <kern/ipc_sched.h>
                     43: #include <kern/task.h>
                     44: #include <kern/thread.h>
                     45: #include <kern/time_out.h>
                     46: #include <machine/machspl.h>   /* for splsched */
                     47: 
                     48: #if    MACH_FIXPRI
                     49: #include <mach/policy.h>
                     50: #endif /* MACH_FIXPRI */
                     51: 
                     52: 
                     53: 
                     54: /*
                     55:  *     swtch and swtch_pri both attempt to context switch (logic in
                     56:  *     thread_block no-ops the context switch if nothing would happen).
                     57:  *     A boolean is returned that indicates whether there is anything
                     58:  *     else runnable.
                     59:  *
                     60:  *     This boolean can be used by a thread waiting on a
                     61:  *     lock or condition:  If FALSE is returned, the thread is justified
                     62:  *     in becoming a resource hog by continuing to spin because there's
                     63:  *     nothing else useful that the processor could do.  If TRUE is
                     64:  *     returned, the thread should make one more check on the
                     65:  *     lock and then be a good citizen and really suspend.
                     66:  */
                     67: 
                     68: extern void thread_depress_priority();
                     69: extern kern_return_t thread_depress_abort();
                     70: 
                     71: #ifdef CONTINUATIONS
                     72: void swtch_continue()
                     73: {
                     74:        register processor_t    myprocessor;
                     75: 
                     76:        myprocessor = current_processor();
                     77:        thread_syscall_return(myprocessor->runq.count > 0 ||
                     78:                              myprocessor->processor_set->runq.count > 0);
                     79:        /*NOTREACHED*/
                     80: }
                     81: #else  /* not CONTINUATIONS */
                     82: #define swtch_continue 0
                     83: #endif /* not CONTINUATIONS */
                     84: 
                     85: boolean_t swtch()
                     86: {
                     87:        register processor_t    myprocessor;
                     88: 
                     89: #if    NCPUS > 1
                     90:        myprocessor = current_processor();
                     91:        if (myprocessor->runq.count == 0 &&
                     92:            myprocessor->processor_set->runq.count == 0)
                     93:                return(FALSE);
                     94: #endif /* NCPUS > 1 */
                     95: 
                     96:        counter(c_swtch_block++);
                     97:        thread_block(swtch_continue);
                     98:        myprocessor = current_processor();
                     99:        return(myprocessor->runq.count > 0 ||
                    100:               myprocessor->processor_set->runq.count > 0);
                    101: }
                    102: 
                    103: #ifdef CONTINUATIONS
                    104: void swtch_pri_continue()
                    105: {
                    106:        register thread_t       thread = current_thread();
                    107:        register processor_t    myprocessor;
                    108: 
                    109:        if (thread->depress_priority >= 0)
                    110:                (void) thread_depress_abort(thread);
                    111:        myprocessor = current_processor();
                    112:        thread_syscall_return(myprocessor->runq.count > 0 ||
                    113:                              myprocessor->processor_set->runq.count > 0);
                    114:        /*NOTREACHED*/
                    115: }
                    116: #else  /* not CONTINUATIONS */
                    117: #define swtch_pri_continue 0
                    118: #endif /* not CONTINUATIONS */
                    119: 
                    120: boolean_t  swtch_pri(pri)
                    121:        int pri;
                    122: {
                    123:        register thread_t       thread = current_thread();
                    124:        register processor_t    myprocessor;
                    125: 
                    126: #ifdef lint
                    127:        pri++;
                    128: #endif /* lint */
                    129: 
                    130: #if    NCPUS > 1
                    131:        myprocessor = current_processor();
                    132:        if (myprocessor->runq.count == 0 &&
                    133:            myprocessor->processor_set->runq.count == 0)
                    134:                return(FALSE);
                    135: #endif /* NCPUS > 1 */
                    136: 
                    137:        /*
                    138:         *      XXX need to think about depression duration.
                    139:         *      XXX currently using min quantum.
                    140:         */
                    141:        thread_depress_priority(thread, min_quantum);
                    142: 
                    143:        counter(c_swtch_pri_block++);
                    144:        thread_block(swtch_pri_continue);
                    145: 
                    146:        if (thread->depress_priority >= 0)
                    147:                (void) thread_depress_abort(thread);
                    148:        myprocessor = current_processor();
                    149:        return(myprocessor->runq.count > 0 ||
                    150:               myprocessor->processor_set->runq.count > 0);
                    151: }
                    152: 
                    153: extern int hz;
                    154: 
                    155: #ifdef CONTINUATIONS
                    156: void thread_switch_continue()
                    157: {
                    158:        register thread_t       cur_thread = current_thread();
                    159: 
                    160:        /*
                    161:         *  Restore depressed priority
                    162:         */
                    163:        if (cur_thread->depress_priority >= 0)
                    164:                (void) thread_depress_abort(cur_thread);
                    165:        thread_syscall_return(KERN_SUCCESS);
                    166:        /*NOTREACHED*/
                    167: }
                    168: #else  /* not CONTINUATIONS */
                    169: #define thread_switch_continue 0
                    170: #endif /* not CONTINUATIONS */
                    171: 
                    172: /*
                    173:  *     thread_switch:
                    174:  *
                    175:  *     Context switch.  User may supply thread hint.
                    176:  *
                    177:  *     Fixed priority threads that call this get what they asked for
                    178:  *     even if that violates priority order.
                    179:  */
                    180: kern_return_t thread_switch(thread_name, option, option_time)
                    181: mach_port_t thread_name;
                    182: int option;
                    183: mach_msg_timeout_t option_time;
                    184: {
                    185:     register thread_t          cur_thread = current_thread();
                    186:     register processor_t       myprocessor;
                    187:     ipc_port_t                 port;
                    188: 
                    189:     /*
                    190:      * Process option.
                    191:      */
                    192:     switch (option) {
                    193:        case SWITCH_OPTION_NONE:
                    194:            /*
                    195:             *  Nothing to do.
                    196:             */
                    197:            break;
                    198: 
                    199:        case SWITCH_OPTION_DEPRESS:
                    200:            /*
                    201:             *  Depress priority for given time.
                    202:             */
                    203:            thread_depress_priority(cur_thread, option_time);
                    204:            break;
                    205: 
                    206:        case SWITCH_OPTION_WAIT:
                    207:            thread_will_wait_with_timeout(cur_thread, option_time);
                    208:            break;
                    209: 
                    210:        default:
                    211:            return(KERN_INVALID_ARGUMENT);
                    212:     }
                    213: 
                    214: #ifndef MIGRATING_THREADS /* XXX thread_run defunct */
                    215:     /*
                    216:      * Check and act on thread hint if appropriate.
                    217:      */
                    218:     if ((thread_name != 0) &&
                    219:        (ipc_port_translate_send(cur_thread->task->itk_space,
                    220:                                 thread_name, &port) == KERN_SUCCESS)) {
                    221:            /* port is locked, but it might not be active */
                    222: 
                    223:            /*
                    224:             *  Get corresponding thread.
                    225:             */
                    226:            if (ip_active(port) && (ip_kotype(port) == IKOT_THREAD)) {
                    227:                register thread_t thread;
                    228:                register spl_t s;
                    229: 
                    230:                thread = (thread_t) port->ip_kobject;
                    231:                /*
                    232:                 *      Check if the thread is in the right pset. Then
                    233:                 *      pull it off its run queue.  If it
                    234:                 *      doesn't come, then it's not eligible.
                    235:                 */
                    236:                s = splsched();
                    237:                thread_lock(thread);
                    238:                if ((thread->processor_set == cur_thread->processor_set)
                    239:                    && (rem_runq(thread) != RUN_QUEUE_NULL)) {
                    240:                        /*
                    241:                         *      Hah, got it!!
                    242:                         */
                    243:                        thread_unlock(thread);
                    244:                        (void) splx(s);
                    245:                        ip_unlock(port);
                    246:                        /* XXX thread might disappear on us now? */
                    247: #if    MACH_FIXPRI
                    248:                        if (thread->policy == POLICY_FIXEDPRI) {
                    249:                            myprocessor = current_processor();
                    250:                            myprocessor->quantum = thread->sched_data;
                    251:                            myprocessor->first_quantum = TRUE;
                    252:                        }
                    253: #endif /* MACH_FIXPRI */
                    254:                        counter(c_thread_switch_handoff++);
                    255:                        thread_run(thread_switch_continue, thread);
                    256:                        /*
                    257:                         *  Restore depressed priority
                    258:                         */
                    259:                        if (cur_thread->depress_priority >= 0)
                    260:                                (void) thread_depress_abort(cur_thread);
                    261: 
                    262:                        return(KERN_SUCCESS);
                    263:                }
                    264:                thread_unlock(thread);
                    265:                (void) splx(s);
                    266:            }
                    267:            ip_unlock(port);
                    268:     }
                    269: #endif /* not MIGRATING_THREADS */
                    270: 
                    271:     /*
                    272:      * No handoff hint supplied, or hint was wrong.  Call thread_block() in
                    273:      * hopes of running something else.  If nothing else is runnable,
                    274:      * thread_block will detect this.  WARNING: thread_switch with no
                    275:      * option will not do anything useful if the thread calling it is the
                    276:      * highest priority thread (can easily happen with a collection
                    277:      * of timesharing threads).
                    278:      */
                    279: #if    NCPUS > 1
                    280:     myprocessor = current_processor();
                    281:     if (myprocessor->processor_set->runq.count > 0 ||
                    282:        myprocessor->runq.count > 0)
                    283: #endif /* NCPUS > 1 */
                    284:     {
                    285:        counter(c_thread_switch_block++);
                    286:        thread_block(thread_switch_continue);
                    287:     }
                    288: 
                    289:     /*
                    290:      *  Restore depressed priority
                    291:      */
                    292:     if (cur_thread->depress_priority >= 0)
                    293:        (void) thread_depress_abort(cur_thread);
                    294:     return(KERN_SUCCESS);
                    295: }
                    296: 
                    297: /*
                    298:  *     thread_depress_priority
                    299:  *
                    300:  *     Depress thread's priority to lowest possible for specified period.
                    301:  *     Intended for use when thread wants a lock but doesn't know which
                    302:  *     other thread is holding it.  As with thread_switch, fixed
                    303:  *     priority threads get exactly what they asked for.  Users access
                    304:  *     this by the SWITCH_OPTION_DEPRESS option to thread_switch.  A Time
                    305:  *      of zero will result in no timeout being scheduled.
                    306:  */
                    307: void
                    308: thread_depress_priority(thread, depress_time)
                    309: register thread_t thread;
                    310: mach_msg_timeout_t depress_time;
                    311: {
                    312:     unsigned int ticks;
                    313:     spl_t      s;
                    314: 
                    315:     /* convert from milliseconds to ticks */
                    316:     ticks = convert_ipc_timeout_to_ticks(depress_time);
                    317: 
                    318:     s = splsched();
                    319:     thread_lock(thread);
                    320: 
                    321:     /*
                    322:      * If thread is already depressed, override previous depression.
                    323:      */
                    324:     reset_timeout_check(&thread->depress_timer);
                    325: 
                    326:     /*
                    327:      * Save current priority, then set priority and
                    328:      * sched_pri to their lowest possible values.
                    329:      */
                    330:     thread->depress_priority = thread->priority;
                    331:     thread->priority = 31;
                    332:     thread->sched_pri = 31;
                    333:     if (ticks != 0)
                    334:        set_timeout(&thread->depress_timer, ticks);
                    335: 
                    336:     thread_unlock(thread);
                    337:     (void) splx(s);
                    338: }
                    339: 
                    340: /*
                    341:  *     thread_depress_timeout:
                    342:  *
                    343:  *     Timeout routine for priority depression.
                    344:  */
                    345: void
                    346: thread_depress_timeout(thread)
                    347: register thread_t thread;
                    348: {
                    349:     spl_t      s;
                    350: 
                    351:     s = splsched();
                    352:     thread_lock(thread);
                    353: 
                    354:     /*
                    355:      * If we lose a race with thread_depress_abort,
                    356:      * then depress_priority might be -1.
                    357:      */
                    358: 
                    359:     if (thread->depress_priority >= 0) {
                    360:        thread->priority = thread->depress_priority;
                    361:        thread->depress_priority = -1;
                    362:        compute_priority(thread, FALSE);
                    363:     }
                    364: 
                    365:     thread_unlock(thread);
                    366:     (void) splx(s);
                    367: }
                    368: 
                    369: /*
                    370:  *     thread_depress_abort:
                    371:  *
                    372:  *     Prematurely abort priority depression if there is one.
                    373:  */
                    374: kern_return_t
                    375: thread_depress_abort(thread)
                    376: register thread_t      thread;
                    377: {
                    378:     spl_t      s;
                    379: 
                    380:     if (thread == THREAD_NULL)
                    381:        return(KERN_INVALID_ARGUMENT);
                    382: 
                    383:     s = splsched();
                    384:     thread_lock(thread);
                    385: 
                    386:     /*
                    387:      * Only restore priority if thread is depressed.
                    388:      */
                    389:     if (thread->depress_priority >= 0) {
                    390:        reset_timeout_check(&thread->depress_timer);
                    391:        thread->priority = thread->depress_priority;
                    392:        thread->depress_priority = -1;
                    393:        compute_priority(thread, FALSE);
                    394:     }
                    395: 
                    396:     thread_unlock(thread);
                    397:     (void) splx(s);
                    398:     return(KERN_SUCCESS);
                    399: }

unix.superglobalmegacorp.com

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