Annotation of Gnu-Mach/kern/ipc_sched.c, revision 1.1.1.2

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1993, 1992,1991,1990 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
                     11:  * 
                     12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: 
                     27: #include <mach/message.h>
                     28: #include <kern/counters.h>
                     29: #include "cpu_number.h"
1.1.1.2 ! root       30: #include <kern/debug.h>
1.1       root       31: #include <kern/lock.h>
1.1.1.2 ! root       32: #include <kern/mach_clock.h>
1.1       root       33: #include <kern/thread.h>
                     34: #include <kern/sched_prim.h>
                     35: #include <kern/processor.h>
                     36: #include <kern/thread_swap.h>
                     37: #include <kern/ipc_sched.h>
                     38: #include <machine/machspl.h>   /* for splsched/splx */
                     39: #include <machine/pmap.h>
                     40: 
                     41: 
                     42: 
                     43: /*
                     44:  *     These functions really belong in kern/sched_prim.c.
                     45:  */
                     46: 
                     47: /*
                     48:  *     Routine:        thread_go
                     49:  *     Purpose:
                     50:  *             Start a thread running.
                     51:  *     Conditions:
                     52:  *             IPC locks may be held.
                     53:  */
                     54: 
                     55: void
                     56: thread_go(
                     57:        thread_t thread)
                     58: {
                     59:        int     state;
                     60:        spl_t   s;
                     61: 
                     62:        s = splsched();
                     63:        thread_lock(thread);
                     64: 
                     65:        reset_timeout_check(&thread->timer);
                     66: 
                     67:        state = thread->state;
                     68:        switch (state & TH_SCHED_STATE) {
                     69: 
                     70:            case TH_WAIT | TH_SUSP | TH_UNINT:
                     71:            case TH_WAIT           | TH_UNINT:
                     72:            case TH_WAIT:
                     73:                /*
                     74:                 *      Sleeping and not suspendable - put
                     75:                 *      on run queue.
                     76:                 */
                     77:                thread->state = (state &~ TH_WAIT) | TH_RUN;
                     78:                thread->wait_result = THREAD_AWAKENED;
                     79:                thread_setrun(thread, TRUE);
                     80:                break;
                     81: 
                     82:            case          TH_WAIT | TH_SUSP:
                     83:            case TH_RUN | TH_WAIT:
                     84:            case TH_RUN | TH_WAIT | TH_SUSP:
                     85:            case TH_RUN | TH_WAIT           | TH_UNINT:
                     86:            case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
                     87:                /*
                     88:                 *      Either already running, or suspended.
                     89:                 */
                     90:                thread->state = state & ~TH_WAIT;
                     91:                thread->wait_result = THREAD_AWAKENED;
                     92:                break;
                     93: 
                     94:            default:
                     95:                /*
                     96:                 *      Not waiting.
                     97:                 */
                     98:                break;
                     99:        }
                    100: 
                    101:        thread_unlock(thread);
                    102:        splx(s);
                    103: }
                    104: 
                    105: /*
                    106:  *     Routine:        thread_will_wait
                    107:  *     Purpose:
                    108:  *             Assert that the thread intends to block.
                    109:  */
                    110: 
                    111: void
                    112: thread_will_wait(
                    113:        thread_t thread)
                    114: {
                    115:        spl_t   s;
                    116: 
                    117:        s = splsched();
                    118:        thread_lock(thread);
                    119: 
                    120:        assert(thread->wait_result = -1);       /* for later assertions */
                    121:        thread->state |= TH_WAIT;
                    122: 
                    123:        thread_unlock(thread);
                    124:        splx(s);
                    125: }
                    126: 
                    127: /*
                    128:  *     Routine:        thread_will_wait_with_timeout
                    129:  *     Purpose:
                    130:  *             Assert that the thread intends to block,
                    131:  *             with a timeout.
                    132:  */
                    133: 
                    134: void
                    135: thread_will_wait_with_timeout(
                    136:        thread_t thread,
                    137:        mach_msg_timeout_t msecs)
                    138: {
                    139:        natural_t ticks = convert_ipc_timeout_to_ticks(msecs);
                    140:        spl_t   s;
                    141: 
                    142:        s = splsched();
                    143:        thread_lock(thread);
                    144: 
                    145:        assert(thread->wait_result = -1);       /* for later assertions */
                    146:        thread->state |= TH_WAIT;
                    147: 
                    148:        set_timeout(&thread->timer, ticks);
                    149: 
                    150:        thread_unlock(thread);
                    151:        splx(s);
                    152: }
                    153: 
                    154: #if    MACH_HOST
                    155: #define check_processor_set(thread)    \
                    156:            (current_processor()->processor_set == (thread)->processor_set)
                    157: #else  /* MACH_HOST */
                    158: #define        check_processor_set(thread)     TRUE
                    159: #endif /* MACH_HOST */
                    160: 
                    161: #if    NCPUS > 1
                    162: #define        check_bound_processor(thread) \
                    163:            ((thread)->bound_processor == PROCESSOR_NULL || \
                    164:             (thread)->bound_processor == current_processor())
                    165: #else  /* NCPUS > 1 */
                    166: #define        check_bound_processor(thread)   TRUE
                    167: #endif /* NCPUS > 1 */
                    168: 
                    169: /*
                    170:  *     Routine:        thread_handoff
                    171:  *     Purpose:
                    172:  *             Switch to a new thread (new), leaving the current
                    173:  *             thread (old) blocked.  If successful, moves the
                    174:  *             kernel stack from old to new and returns as the
                    175:  *             new thread.  An explicit continuation for the old thread
                    176:  *             must be supplied.
                    177:  *
                    178:  *             NOTE:  Although we wakeup new, we don't set new->wait_result.
                    179:  *     Returns:
                    180:  *             TRUE if the handoff happened.
                    181:  */
                    182: 
                    183: boolean_t
                    184: thread_handoff(
                    185:        register thread_t old,
                    186:        register continuation_t continuation,
                    187:        register thread_t new)
                    188: {
                    189:        spl_t   s;
                    190: 
                    191:        assert(current_thread() == old);
                    192: 
                    193:        /*
                    194:         *      XXX Dubious things here:
                    195:         *      I don't check the idle_count on the processor set.
                    196:         *      No scheduling priority or policy checks.
                    197:         *      I assume the new thread is interruptible.
                    198:         */
                    199: 
                    200:        s = splsched();
                    201:        thread_lock(new);
                    202: 
                    203:        /*
                    204:         *      The first thing we must do is check the state
                    205:         *      of the threads, to ensure we can handoff.
                    206:         *      This check uses current_processor()->processor_set,
                    207:         *      which we can read without locking.
                    208:         */
                    209: 
                    210:        if ((old->stack_privilege == current_stack()) ||
                    211:            (new->state != (TH_WAIT|TH_SWAPPED)) ||
                    212:             !check_processor_set(new) ||
                    213:             !check_bound_processor(new)) {
                    214:                thread_unlock(new);
                    215:                (void) splx(s);
                    216: 
                    217:                counter_always(c_thread_handoff_misses++);
                    218:                return FALSE;
                    219:        }
                    220: 
                    221:        reset_timeout_check(&new->timer);
                    222: 
                    223:        new->state = TH_RUN;
                    224:        thread_unlock(new);
                    225: 
                    226: #if    NCPUS > 1
                    227:        new->last_processor = current_processor();
                    228: #endif /* NCPUS > 1 */
                    229: 
                    230:        ast_context(new, cpu_number());
                    231:        timer_switch(&new->system_timer);
                    232: 
                    233:        /*
                    234:         *      stack_handoff is machine-dependent.  It does the
                    235:         *      machine-dependent components of a context-switch, like
                    236:         *      changing address spaces.  It updates active_threads.
                    237:         */
                    238: 
                    239:        stack_handoff(old, new);
                    240: 
                    241:        /*
                    242:         *      Now we must dispose of the old thread.
                    243:         *      This is like thread_continue, except
                    244:         *      that the old thread isn't waiting yet.
                    245:         */
                    246: 
                    247:        thread_lock(old);
                    248:        old->swap_func = continuation;
                    249:        assert(old->wait_result = -1);          /* for later assertions */
                    250: 
                    251:        if (old->state == TH_RUN) {
                    252:                /*
                    253:                 *      This is our fast path.
                    254:                 */
                    255: 
                    256:                old->state = TH_WAIT|TH_SWAPPED;
                    257:        }
                    258:        else if (old->state == (TH_RUN|TH_SUSP)) {
                    259:                /*
                    260:                 *      Somebody is trying to suspend the thread.
                    261:                 */
                    262: 
                    263:                old->state = TH_WAIT|TH_SUSP|TH_SWAPPED;
                    264:                if (old->wake_active) {
                    265:                        /*
                    266:                         *      Someone wants to know when the thread
                    267:                         *      really stops.
                    268:                         */
                    269:                        old->wake_active = FALSE;
                    270:                        thread_unlock(old);
                    271:                        thread_wakeup((event_t)&old->wake_active);
                    272:                        goto after_old_thread;
                    273:                }
                    274:        } else
                    275:                panic("thread_handoff");
                    276: 
                    277:        thread_unlock(old);
                    278:     after_old_thread:
                    279:        (void) splx(s);
                    280: 
                    281:        counter_always(c_thread_handoff_hits++);
                    282:        return TRUE;
                    283: }

unix.superglobalmegacorp.com

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