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

unix.superglobalmegacorp.com

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