Annotation of XNU/osfmk/kern/ast.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /* 
                     51:  */
                     52: 
                     53: /*
                     54:  *
                     55:  *     This file contains routines to check whether an ast is needed.
                     56:  *
                     57:  *     ast_check() - check whether ast is needed for interrupt or context
                     58:  *     switch.  Usually called by clock interrupt handler.
                     59:  *
                     60:  */
                     61: 
                     62: #include <cputypes.h>
                     63: #include <cpus.h>
                     64: #include <platforms.h>
                     65: #include <dipc.h>
                     66: #include <task_swapper.h>
                     67: 
                     68: #include <kern/ast.h>
                     69: #include <kern/counters.h>
                     70: #include <kern/cpu_number.h>
                     71: #include <kern/misc_protos.h>
                     72: #include <kern/queue.h>
                     73: #include <kern/sched.h>
                     74: #include <kern/sched_prim.h>
                     75: #include <kern/thread.h>
                     76: #include <kern/thread_act.h>
                     77: #include <kern/thread_swap.h>
                     78: #include <kern/processor.h>
                     79: #include <kern/spl.h>
                     80: #include <mach/policy.h>
                     81: #if    DIPC
                     82: #include <dipc/dipc_funcs.h>
                     83: #endif /* DIPC */
                     84: #if    TASK_SWAPPER
                     85: #include <kern/task_swap.h>
                     86: #endif /* TASK_SWAPPER */
                     87: 
                     88: volatile ast_t need_ast[NCPUS];
                     89: 
                     90: void
                     91: ast_init(void)
                     92: {
                     93: #ifndef        MACHINE_AST
                     94:        register int i;
                     95: 
                     96:        for (i=0; i<NCPUS; i++) {
                     97:                need_ast[i] = AST_NONE;
                     98:        }
                     99: #endif /* MACHINE_AST */
                    100: }
                    101: 
                    102: void
                    103: ast_taken(
                    104:        boolean_t               preemption,
                    105:        ast_t                   mask,
                    106:        boolean_t               interrupt
                    107: )
                    108: {
                    109:        register thread_t       self = current_thread();
                    110:        register processor_t    mypr;
                    111:        register ast_t          reasons;
                    112:        register int            mycpu;
                    113:        thread_act_t            act = self->top_act;
                    114: #ifdef MACH_BSD
                    115:        extern void             bsd_ast(thread_act_t);
                    116: #endif
                    117: 
                    118:        mp_disable_preemption();
                    119:        mycpu = cpu_number();
                    120:        reasons = need_ast[mycpu] & mask;
                    121:        need_ast[mycpu] &= ~reasons;
                    122:        mp_enable_preemption();
                    123: 
                    124:        ml_set_interrupts_enabled(interrupt);
                    125: 
                    126:        /*
                    127:         *      These actions must not block.
                    128:         */
                    129: 
                    130: #if    DIPC
                    131:        if (reasons & AST_DIPC)
                    132:                dipc_ast();
                    133: #endif /* DIPC */
                    134: 
                    135: #ifdef MACH_BSD
                    136:        if (reasons & AST_BSD)
                    137:                bsd_ast(act);
                    138:        if (reasons & AST_BSD_INIT) {
                    139:                thread_ast_clear(act,AST_BSD_INIT);
                    140:                bsdinit_task();
                    141:        }
                    142: #endif
                    143: 
                    144:        /*
                    145:         *      Make darn sure that we don't call thread_halt_self
                    146:         *      or thread_block from the idle thread.
                    147:         */
                    148: 
                    149:        /* XXX - this isn't currently right for the HALT case... */
                    150: 
                    151:        mp_disable_preemption();
                    152:        mypr = current_processor();
                    153:        if (self == mypr->idle_thread) {
                    154: #if    NCPUS == 1
                    155:            if (reasons & AST_URGENT) {
                    156:                if (!preemption)
                    157:                    panic("ast_taken: AST_URGENT for idle_thr w/o preemption");
                    158:            }
                    159: #endif
                    160:            mp_enable_preemption();
                    161:            return;
                    162:        }
                    163:        mp_enable_preemption();
                    164: 
                    165: #if    TASK_SWAPPER
                    166:        /* must be before AST_APC */
                    167:        if (reasons & AST_SWAPOUT) {
                    168:                spl_t s;
                    169:                swapout_ast();
                    170:                s = splsched();
                    171:                mp_disable_preemption();
                    172:                mycpu = cpu_number();
                    173:                if (need_ast[mycpu] & AST_APC) {
                    174:                        /* generated in swapout_ast() to get suspended */
                    175:                        reasons |= AST_APC;             /* process now ... */
                    176:                        need_ast[mycpu] &= ~AST_APC;    /* ... and not later */
                    177:                }
                    178:                mp_enable_preemption();
                    179:                splx(s);
                    180:        }
                    181: #endif /* TASK_SWAPPER */
                    182: 
                    183:        /* migration APC hook */
                    184:        if (reasons & AST_APC) {
                    185:                act_execute_returnhandlers();
                    186:                return; /* auto-retry will catch anything new */
                    187:        }
                    188: 
                    189:        /* 
                    190:         *      thread_block needs to know if the thread's quantum 
                    191:         *      expired so the thread can be put on the tail of
                    192:         *      run queue. One of the previous actions might well
                    193:         *      have woken a high-priority thread, so we also use
                    194:         *      csw_needed check.
                    195:         */
                    196:        {   
                    197:            if ((reasons &= AST_PREEMPT) == 0) {
                    198:                    mp_disable_preemption();
                    199:                    mypr = current_processor();
                    200:                    if (csw_needed(self, mypr)) {
                    201:                            reasons = (mypr->first_quantum
                    202:                                       ? AST_BLOCK
                    203:                                       : AST_QUANTUM);
                    204:                    }
                    205:                    mp_enable_preemption();
                    206:            }
                    207:            if (reasons) {
                    208:                    counter(c_ast_taken_block++);
                    209:                    thread_block_reason((void (*)(void))0, reasons);
                    210:            }
                    211:        }
                    212: }
                    213: 
                    214: void
                    215: ast_check(void)
                    216: {
                    217:        register int            mycpu;
                    218:        register processor_t    myprocessor;
                    219:        register thread_t       thread = current_thread();
                    220:        spl_t                   s = splsched();
                    221: 
                    222:        mp_disable_preemption();
                    223:        mycpu = cpu_number();
                    224: 
                    225:        /*
                    226:         *      Check processor state for ast conditions.
                    227:         */
                    228:        myprocessor = cpu_to_processor(mycpu);
                    229:        switch(myprocessor->state) {
                    230:            case PROCESSOR_OFF_LINE:
                    231:            case PROCESSOR_IDLE:
                    232:            case PROCESSOR_DISPATCHING:
                    233:                /*
                    234:                 *      No ast.
                    235:                 */
                    236:                break;
                    237: 
                    238: #if    NCPUS > 1
                    239:            case PROCESSOR_ASSIGN:
                    240:            case PROCESSOR_SHUTDOWN:
                    241:                /*
                    242:                 *      Need ast to force action thread onto processor.
                    243:                 *
                    244:                 * XXX  Should check if action thread is already there.
                    245:                 */
                    246:                ast_on(AST_BLOCK);
                    247:                break;
                    248: #endif /* NCPUS > 1 */
                    249: 
                    250:            case PROCESSOR_RUNNING:
                    251:                /*
                    252:                 *      Propagate thread ast to processor.  If we already
                    253:                 *      need an ast, don't look for more reasons.
                    254:                 */
                    255:                ast_propagate(current_act()->ast);
                    256:                if (ast_needed(mycpu))
                    257:                        break;
                    258: 
                    259:                /*
                    260:                 *      Context switch check.
                    261:                 */
                    262:                if (csw_needed(thread, myprocessor)) {
                    263:                        ast_on((myprocessor->first_quantum ?
                    264:                               AST_BLOCK : AST_QUANTUM));
                    265:                }
                    266:                break;
                    267: 
                    268:            default:
                    269:                panic("ast_check: Bad processor state");
                    270:        }
                    271:        mp_enable_preemption();
                    272:        splx(s);
                    273: }
                    274: 
                    275: /*
                    276:  * JMM - Temporary exports to other components
                    277:  */
                    278: #undef ast_on
                    279: #undef ast_off
                    280: 
                    281: void
                    282: ast_on(ast_t reason)
                    283: {
                    284:        ast_on_fast(reason);
                    285: }
                    286: 
                    287: void
                    288: ast_off(ast_t reason)
                    289: {
                    290:        ast_off_fast(reason);
                    291: }

unix.superglobalmegacorp.com

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