Annotation of OSKit-Mach/kern/ast.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:  *
                     31:  *     This file contains routines to check whether an ast is needed.
                     32:  *
                     33:  *     ast_check() - check whether ast is needed for interrupt or context
                     34:  *     switch.  Usually called by clock interrupt handler.
                     35:  *
                     36:  */
                     37: 
                     38: #include <cpus.h>
                     39: #include <mach_fixpri.h>
                     40: #include <norma_ipc.h>
                     41: 
                     42: #include <kern/ast.h>
                     43: #include <kern/counters.h>
                     44: #include "cpu_number.h"
                     45: #include <kern/queue.h>
                     46: #include <kern/sched.h>
                     47: #include <kern/sched_prim.h>
                     48: #include <kern/thread.h>
                     49: #include <kern/processor.h>
                     50: 
                     51: #include <machine/machspl.h>   /* for splsched */
                     52: 
                     53: #if    MACH_FIXPRI
                     54: #include <mach/policy.h>
                     55: #endif /* MACH_FIXPRI */
                     56: 
                     57: 
                     58: volatile ast_t need_ast[NCPUS];
                     59: 
                     60: void
                     61: ast_init()
                     62: {
                     63: #ifndef        MACHINE_AST
                     64:        register int i;
                     65: 
                     66:        for (i=0; i<NCPUS; i++)
                     67:                need_ast[i] = 0;
                     68: #endif /* MACHINE_AST */
                     69: }
                     70: 
                     71: void
                     72: ast_taken()
                     73: {
                     74:        register thread_t self = current_thread();
                     75:        register ast_t reasons;
                     76: 
                     77:        /*
                     78:         *      Interrupts are still disabled.
                     79:         *      We must clear need_ast and then enable interrupts.
                     80:         */
                     81: 
                     82:        reasons = need_ast[cpu_number()];
                     83:        need_ast[cpu_number()] = AST_ZILCH;
                     84:        (void) spl0();
                     85: 
                     86:        /*
                     87:         *      These actions must not block.
                     88:         */
                     89: 
                     90:        if (reasons & AST_NETWORK)
                     91:                net_ast();
                     92: 
                     93: #if    NORMA_IPC
                     94:        if (reasons & AST_NETIPC)
                     95:                netipc_ast();
                     96: #endif /* NORMA_IPC */
                     97: 
                     98:        /*
                     99:         *      Make darn sure that we don't call thread_halt_self
                    100:         *      or thread_block from the idle thread.
                    101:         */
                    102: 
                    103:        if (self != current_processor()->idle_thread) {
                    104: #ifndef MIGRATING_THREADS
                    105:                while (thread_should_halt(self))
                    106:                        thread_halt_self();
                    107: #endif
                    108: 
                    109:                /*
                    110:                 *      One of the previous actions might well have
                    111:                 *      woken a high-priority thread, so we use
                    112:                 *      csw_needed in addition to AST_BLOCK.
                    113:                 */
                    114: 
                    115:                if ((reasons & AST_BLOCK) ||
                    116:                    csw_needed(self, current_processor())) {
                    117:                        counter(c_ast_taken_block++);
                    118:                        thread_block(thread_exception_return);
                    119:                }
                    120:        }
                    121: }
                    122: 
                    123: void
                    124: ast_check()
                    125: {
                    126:        register int            mycpu = cpu_number();
                    127:        register processor_t    myprocessor;
                    128:        register thread_t       thread = current_thread();
                    129:        register run_queue_t    rq;
                    130:        spl_t                   s = splsched();
                    131: 
                    132:        /*
                    133:         *      Check processor state for ast conditions.
                    134:         */
                    135:        myprocessor = cpu_to_processor(mycpu);
                    136:        switch(myprocessor->state) {
                    137:            case PROCESSOR_OFF_LINE:
                    138:            case PROCESSOR_IDLE:
                    139:            case PROCESSOR_DISPATCHING:
                    140:                /*
                    141:                 *      No ast.
                    142:                 */
                    143:                break;
                    144: 
                    145: #if    NCPUS > 1
                    146:            case PROCESSOR_ASSIGN:
                    147:            case PROCESSOR_SHUTDOWN:
                    148:                /*
                    149:                 *      Need ast to force action thread onto processor.
                    150:                 *
                    151:                 * XXX  Should check if action thread is already there.
                    152:                 */
                    153:                ast_on(mycpu, AST_BLOCK);
                    154:                break;
                    155: #endif /* NCPUS > 1 */
                    156: 
                    157:            case PROCESSOR_RUNNING:
                    158: 
                    159:                /*
                    160:                 *      Propagate thread ast to processor.  If we already
                    161:                 *      need an ast, don't look for more reasons.
                    162:                 */
                    163:                ast_propagate(thread, mycpu);
                    164:                if (ast_needed(mycpu))
                    165:                        break;
                    166: 
                    167:                /*
                    168:                 *      Context switch check.  The csw_needed macro isn't
                    169:                 *      used here because the rq->low hint may be wrong,
                    170:                 *      and fixing it here avoids an extra ast.
                    171:                 *      First check the easy cases.
                    172:                 */
                    173:                if (thread->state & TH_SUSP || myprocessor->runq.count > 0) {
                    174:                        ast_on(mycpu, AST_BLOCK);
                    175:                        break;
                    176:                }
                    177: 
                    178:                /*
                    179:                 *      Update lazy evaluated runq->low if only timesharing.
                    180:                 */
                    181: #if    MACH_FIXPRI
                    182:                if (myprocessor->processor_set->policies & POLICY_FIXEDPRI) {
                    183:                    if (csw_needed(thread,myprocessor)) {
                    184:                        ast_on(mycpu, AST_BLOCK);
                    185:                        break;
                    186:                    }
                    187:                    else {
                    188:                        /*
                    189:                         *      For fixed priority threads, set first_quantum
                    190:                         *      so entire new quantum is used.
                    191:                         */
                    192:                        if (thread->policy == POLICY_FIXEDPRI)
                    193:                            myprocessor->first_quantum = TRUE;
                    194:                    }
                    195:                }
                    196:                else {
                    197: #endif /* MACH_FIXPRI                   */
                    198:                rq = &(myprocessor->processor_set->runq);
                    199:                if (!(myprocessor->first_quantum) && (rq->count > 0)) {
                    200:                    register queue_t    q;
                    201:                    /*
                    202:                     *  This is not the first quantum, and there may
                    203:                     *  be something in the processor_set runq.
                    204:                     *  Check whether low hint is accurate.
                    205:                     */
                    206:                    q = rq->runq + *(volatile int *)&rq->low;
                    207:                    if (queue_empty(q)) {
                    208:                        register int i;
                    209: 
                    210:                        /*
                    211:                         *      Need to recheck and possibly update hint.
                    212:                         */
                    213:                        simple_lock(&rq->lock);
                    214:                        q = rq->runq + rq->low;
                    215:                        if (rq->count > 0) {
                    216:                            for (i = rq->low; i < NRQS; i++) {
                    217:                                if(!(queue_empty(q)))
                    218:                                    break;
                    219:                                q++;
                    220:                            }
                    221:                            rq->low = i;
                    222:                        }
                    223:                        simple_unlock(&rq->lock);
                    224:                    }
                    225: 
                    226:                    if (rq->low <= thread->sched_pri) {
                    227:                        ast_on(mycpu, AST_BLOCK);
                    228:                        break;
                    229:                    }
                    230:                }
                    231: #if    MACH_FIXPRI
                    232:                }
                    233: #endif /* MACH_FIXPRI */
                    234:                break;
                    235: 
                    236:            default:
                    237:                panic("ast_check: Bad processor state (cpu %d processor %08x) state: %d",
                    238:                        mycpu, myprocessor, myprocessor->state);
                    239:        }
                    240: 
                    241:        (void) splx(s);
                    242: }

unix.superglobalmegacorp.com

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