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

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