Annotation of Gnu-Mach/kern/syscall_subr.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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