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

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 <cpus.h>
                     28: #include <mach_host.h>
                     29: 
                     30: #include <mach/message.h>
                     31: #include <kern/counters.h>
                     32: #include "cpu_number.h"
                     33: #include <kern/lock.h>
                     34: #include <kern/thread.h>
                     35: #include <kern/sched_prim.h>
                     36: #include <kern/processor.h>
                     37: #include <kern/time_out.h>
                     38: #include <kern/thread_swap.h>
                     39: #include <kern/ipc_sched.h>
                     40: #include <machine/machspl.h>   /* for splsched/splx */
                     41: #include <machine/pmap.h>
                     42: 
                     43: 
                     44: 
                     45: /*
                     46:  *     These functions really belong in kern/sched_prim.c.
                     47:  */
                     48: 
                     49: /*
                     50:  *     Routine:        thread_go
                     51:  *     Purpose:
                     52:  *             Start a thread running.
                     53:  *     Conditions:
                     54:  *             IPC locks may be held.
                     55:  */
                     56: 
                     57: void
                     58: thread_go(
                     59:        thread_t thread)
                     60: {
                     61:        int     state;
                     62:        spl_t   s;
                     63: 
                     64:        s = splsched();
                     65:        thread_lock(thread);
                     66: 
                     67:        reset_timeout_check(&thread->timer);
                     68: 
                     69:        state = thread->state;
                     70:        switch (state & TH_SCHED_STATE) {
                     71: 
                     72:            case TH_WAIT | TH_SUSP | TH_UNINT:
                     73:            case TH_WAIT           | TH_UNINT:
                     74:            case TH_WAIT:
                     75:                /*
                     76:                 *      Sleeping and not suspendable - put
                     77:                 *      on run queue.
                     78:                 */
                     79:                thread->state = (state &~ TH_WAIT) | TH_RUN;
                     80:                thread->wait_result = THREAD_AWAKENED;
                     81:                thread_setrun(thread, TRUE);
                     82:                break;
                     83: 
                     84:            case          TH_WAIT | TH_SUSP:
                     85:            case TH_RUN | TH_WAIT:
                     86:            case TH_RUN | TH_WAIT | TH_SUSP:
                     87:            case TH_RUN | TH_WAIT           | TH_UNINT:
                     88:            case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT:
                     89:                /*
                     90:                 *      Either already running, or suspended.
                     91:                 */
                     92:                thread->state = state & ~TH_WAIT;
                     93:                thread->wait_result = THREAD_AWAKENED;
                     94:                break;
                     95: 
                     96:            default:
                     97:                /*
                     98:                 *      Not waiting.
                     99:                 */
                    100:                break;
                    101:        }
                    102: 
                    103:        thread_unlock(thread);
                    104:        splx(s);
                    105: }
                    106: 
                    107: /*
                    108:  *     Routine:        thread_will_wait
                    109:  *     Purpose:
                    110:  *             Assert that the thread intends to block.
                    111:  */
                    112: 
                    113: void
                    114: thread_will_wait(
                    115:        thread_t thread)
                    116: {
                    117:        spl_t   s;
                    118: 
                    119:        s = splsched();
                    120:        thread_lock(thread);
                    121: 
                    122:        assert(thread->wait_result = -1);       /* for later assertions */
                    123:        thread->state |= TH_WAIT;
                    124: 
                    125:        thread_unlock(thread);
                    126:        splx(s);
                    127: }
                    128: 
                    129: /*
                    130:  *     Routine:        thread_will_wait_with_timeout
                    131:  *     Purpose:
                    132:  *             Assert that the thread intends to block,
                    133:  *             with a timeout.
                    134:  */
                    135: 
                    136: void
                    137: thread_will_wait_with_timeout(
                    138:        thread_t thread,
                    139:        mach_msg_timeout_t msecs)
                    140: {
                    141:        natural_t ticks = convert_ipc_timeout_to_ticks(msecs);
                    142:        spl_t   s;
                    143: 
                    144:        s = splsched();
                    145:        thread_lock(thread);
                    146: 
                    147:        assert(thread->wait_result = -1);       /* for later assertions */
                    148:        thread->state |= TH_WAIT;
                    149: 
                    150:        set_timeout(&thread->timer, ticks);
                    151: 
                    152:        thread_unlock(thread);
                    153:        splx(s);
                    154: }
                    155: 
                    156: #if    MACH_HOST
                    157: #define check_processor_set(thread)    \
                    158:            (current_processor()->processor_set == (thread)->processor_set)
                    159: #else  /* MACH_HOST */
                    160: #define        check_processor_set(thread)     TRUE
                    161: #endif /* MACH_HOST */
                    162: 
                    163: #if    NCPUS > 1
                    164: #define        check_bound_processor(thread) \
                    165:            ((thread)->bound_processor == PROCESSOR_NULL || \
                    166:             (thread)->bound_processor == current_processor())
                    167: #else  /* NCPUS > 1 */
                    168: #define        check_bound_processor(thread)   TRUE
                    169: #endif /* NCPUS > 1 */
                    170: 
                    171: #ifdef CONTINUATIONS
                    172: /*
                    173:  *     Routine:        thread_handoff
                    174:  *     Purpose:
                    175:  *             Switch to a new thread (new), leaving the current
                    176:  *             thread (old) blocked.  If successful, moves the
                    177:  *             kernel stack from old to new and returns as the
                    178:  *             new thread.  An explicit continuation for the old thread
                    179:  *             must be supplied.
                    180:  *
                    181:  *             NOTE:  Although we wakeup new, we don't set new->wait_result.
                    182:  *     Returns:
                    183:  *             TRUE if the handoff happened.
                    184:  */
                    185: 
                    186: boolean_t
                    187: thread_handoff(
                    188:        register thread_t old,
                    189:        register continuation_t continuation,
                    190:        register thread_t new)
                    191: {
                    192:        spl_t   s;
                    193: 
                    194:        assert(current_thread() == old);
                    195: 
                    196:        /*
                    197:         *      XXX Dubious things here:
                    198:         *      I don't check the idle_count on the processor set.
                    199:         *      No scheduling priority or policy checks.
                    200:         *      I assume the new thread is interruptible.
                    201:         */
                    202: 
                    203:        s = splsched();
                    204:        thread_lock(new);
                    205: 
                    206:        /*
                    207:         *      The first thing we must do is check the state
                    208:         *      of the threads, to ensure we can handoff.
                    209:         *      This check uses current_processor()->processor_set,
                    210:         *      which we can read without locking.
                    211:         */
                    212: 
                    213:        if ((old->stack_privilege == current_stack()) ||
                    214:            (new->state != (TH_WAIT|TH_SWAPPED)) ||
                    215:             !check_processor_set(new) ||
                    216:             !check_bound_processor(new)) {
                    217:                thread_unlock(new);
                    218:                (void) splx(s);
                    219: 
                    220:                counter_always(c_thread_handoff_misses++);
                    221:                return FALSE;
                    222:        }
                    223: 
                    224:        reset_timeout_check(&new->timer);
                    225: 
                    226:        new->state = TH_RUN;
                    227:        thread_unlock(new);
                    228: 
                    229: #if    NCPUS > 1
                    230:        new->last_processor = current_processor();
                    231: #endif /* NCPUS > 1 */
                    232: 
                    233:        ast_context(new, cpu_number());
                    234:        timer_switch(&new->system_timer);
                    235: 
                    236:        /*
                    237:         *      stack_handoff is machine-dependent.  It does the
                    238:         *      machine-dependent components of a context-switch, like
                    239:         *      changing address spaces.  It updates active_threads.
                    240:         */
                    241: 
                    242:        stack_handoff(old, new);
                    243: 
                    244:        /*
                    245:         *      Now we must dispose of the old thread.
                    246:         *      This is like thread_continue, except
                    247:         *      that the old thread isn't waiting yet.
                    248:         */
                    249: 
                    250:        thread_lock(old);
                    251:        old->swap_func = continuation;
                    252:        assert(old->wait_result = -1);          /* for later assertions */
                    253: 
                    254:        if (old->state == TH_RUN) {
                    255:                /*
                    256:                 *      This is our fast path.
                    257:                 */
                    258: 
                    259:                old->state = TH_WAIT|TH_SWAPPED;
                    260:        }
                    261:        else if (old->state == (TH_RUN|TH_SUSP)) {
                    262:                /*
                    263:                 *      Somebody is trying to suspend the thread.
                    264:                 */
                    265: 
                    266:                old->state = TH_WAIT|TH_SUSP|TH_SWAPPED;
                    267:                if (old->wake_active) {
                    268:                        /*
                    269:                         *      Someone wants to know when the thread
                    270:                         *      really stops.
                    271:                         */
                    272:                        old->wake_active = FALSE;
                    273:                        thread_unlock(old);
                    274:                        thread_wakeup((event_t)&old->wake_active);
                    275:                        goto after_old_thread;
                    276:                }
                    277:        } else
                    278:                panic("thread_handoff");
                    279: 
                    280:        thread_unlock(old);
                    281:     after_old_thread:
                    282:        (void) splx(s);
                    283: 
                    284:        counter_always(c_thread_handoff_hits++);
                    285:        return TRUE;
                    286: }
                    287: #endif /* CONTINUATIONS */

unix.superglobalmegacorp.com

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