1/* 2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * Mach Operating System 33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56/* 57 */ 58 59/* 60 * 61 * This file contains routines to check whether an ast is needed. 62 * 63 * ast_check() - check whether ast is needed for interrupt or context 64 * switch. Usually called by clock interrupt handler. 65 * 66 */ 67 68#include <cputypes.h> 69#include <platforms.h> 70 71#include <kern/ast.h> 72#include <kern/counters.h> 73#include <kern/cpu_number.h> 74#include <kern/misc_protos.h> 75#include <kern/queue.h> 76#include <kern/sched_prim.h> 77#include <kern/thread.h> 78#include <kern/processor.h> 79#include <kern/spl.h> 80#include <kern/wait_queue.h> 81#include <mach/policy.h> 82#include <machine/trap.h> // for CHUD AST hook 83 84void 85ast_init(void) 86{ 87} 88 89/* 90 * Called at splsched. 91 */ 92void 93ast_taken( 94 ast_t reasons, 95 boolean_t enable 96) 97{ 98 boolean_t preempt_trap = (reasons == AST_PREEMPTION); 99 ast_t *myast = ast_pending(); 100 thread_t thread = current_thread(); 101 102 /* 103 * CHUD hook - all threads including idle processor threads 104 */ 105 if(perfASTHook) { 106 if(*myast & AST_CHUD_ALL) { 107 perfASTHook(0, NULL, 0, 0); 108 109 if(*myast == AST_NONE) { 110 return; // nothing left to do 111 } 112 } 113 } else { 114 *myast &= ~AST_CHUD_ALL; 115 } 116 117 reasons &= *myast; 118 *myast &= ~reasons; 119 120 /* 121 * Handle ASTs for all threads 122 * except idle processor threads. 123 */ 124 if (!(thread->state & TH_IDLE)) { 125 /* 126 * Check for urgent preemption. 127 */ 128 if ( (reasons & AST_URGENT) && 129 wait_queue_assert_possible(thread) ) { 130 if (reasons & AST_PREEMPT) { 131 counter(c_ast_taken_block++); 132 thread_block_reason(THREAD_CONTINUE_NULL, NULL, 133 AST_PREEMPT | AST_URGENT); 134 } 135 136 reasons &= ~AST_PREEMPTION; 137 } 138 139 /* 140 * The kernel preempt traps 141 * skip all other ASTs. 142 */ 143 if (!preempt_trap) { 144 ml_set_interrupts_enabled(enable); 145 146#ifdef MACH_BSD 147 /* 148 * Handle BSD hook. 149 */ 150 if (reasons & AST_BSD) { 151 thread_ast_clear(thread, AST_BSD); 152 bsd_ast(thread); 153 } 154#endif 155 156 /* 157 * Thread APC hook. 158 */ 159 if (reasons & AST_APC) 160 act_execute_returnhandlers(); 161 162 ml_set_interrupts_enabled(FALSE); 163 164 /* 165 * Check for preemption. 166 */ 167 if (reasons & AST_PREEMPT) 168 reasons = csw_check(current_processor()); 169 170 if ( (reasons & AST_PREEMPT) && 171 wait_queue_assert_possible(thread) ) { 172 counter(c_ast_taken_block++); 173 thread_block_reason((thread_continue_t)thread_exception_return, NULL, AST_PREEMPT); 174 } 175 } 176 } 177 178 ml_set_interrupts_enabled(enable); 179} 180 181/* 182 * Called at splsched. 183 */ 184void 185ast_check( 186 processor_t processor) 187{ 188 thread_t thread = processor->active_thread; 189 190 processor->current_pri = thread->sched_pri; 191 if ( processor->state == PROCESSOR_RUNNING || 192 processor->state == PROCESSOR_SHUTDOWN ) { 193 ast_t preempt; 194 195 /* 196 * Propagate thread ast to processor. 197 */ 198 ast_propagate(thread->ast); 199 200 /* 201 * Context switch check. 202 */ 203 if ((preempt = csw_check(processor)) != AST_NONE) 204 ast_on(preempt); 205 } 206} 207