1/* 2 * Copyright (c) 2000-2010 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 <kern/ledger.h> 82#include <mach/policy.h> 83#include <machine/trap.h> // for CHUD AST hook 84#include <machine/pal_routines.h> 85#include <security/mac_mach_internal.h> // for MACF AST hook 86 87volatile perfASTCallback perfASTHook; 88 89 90void 91ast_init(void) 92{ 93} 94 95extern void chudxnu_thread_ast(thread_t); // XXX this should probably be in a header... 96 97/* 98 * Called at splsched. 99 */ 100void 101ast_taken( 102 ast_t reasons, 103 boolean_t enable 104) 105{ 106 boolean_t preempt_trap = (reasons == AST_PREEMPTION); 107 ast_t *myast = ast_pending(); 108 thread_t thread = current_thread(); 109 perfASTCallback perf_hook = perfASTHook; 110 111 /* 112 * CHUD hook - all threads including idle processor threads 113 */ 114 if (perf_hook) { 115 if (*myast & AST_CHUD_ALL) { 116 (*perf_hook)(reasons, myast); 117 118 if (*myast == AST_NONE) 119 return; 120 } 121 } 122 else 123 *myast &= ~AST_CHUD_ALL; 124 125 reasons &= *myast; 126 *myast &= ~reasons; 127 128 /* 129 * Handle ASTs for all threads 130 * except idle processor threads. 131 */ 132 if (!(thread->state & TH_IDLE)) { 133 /* 134 * Check for urgent preemption. 135 */ 136 if ( (reasons & AST_URGENT) && 137 wait_queue_assert_possible(thread) ) { 138 if (reasons & AST_PREEMPT) { 139 counter(c_ast_taken_block++); 140 thread_block_reason(THREAD_CONTINUE_NULL, NULL, 141 AST_PREEMPT | AST_URGENT); 142 } 143 144 reasons &= ~AST_PREEMPTION; 145 } 146 147 /* 148 * The kernel preempt traps 149 * skip all other ASTs. 150 */ 151 if (!preempt_trap) { 152 ml_set_interrupts_enabled(enable); 153 154#ifdef MACH_BSD 155 /* 156 * Handle BSD hook. 157 */ 158 if (reasons & AST_BSD) { 159 thread_ast_clear(thread, AST_BSD); 160 bsd_ast(thread); 161 } 162#endif 163#if CONFIG_MACF 164 /* 165 * Handle MACF hook. 166 */ 167 if (reasons & AST_MACF) { 168 thread_ast_clear(thread, AST_MACF); 169 mac_thread_userret(thread); 170 } 171#endif 172 /* 173 * Thread APC hook. 174 */ 175 if (reasons & AST_APC) 176 act_execute_returnhandlers(); 177 178 if (reasons & AST_LEDGER) { 179 thread_ast_clear(thread, AST_LEDGER); 180 ledger_ast(thread); 181 } 182 183 /* 184 * Kernel Profiling Hook 185 */ 186 if (reasons & AST_KPERF) 187 { 188 thread_ast_clear(thread, AST_KPERF); 189 chudxnu_thread_ast(thread); 190 } 191 192 ml_set_interrupts_enabled(FALSE); 193 194 /* 195 * Check for preemption. 196 */ 197 if (reasons & AST_PREEMPT) 198 reasons = csw_check(current_processor()); 199 200 if ( (reasons & AST_PREEMPT) && 201 wait_queue_assert_possible(thread) ) { 202 counter(c_ast_taken_block++); 203 thread_block_reason((thread_continue_t)thread_exception_return, NULL, AST_PREEMPT); 204 } 205 } 206 } 207 208 ml_set_interrupts_enabled(enable); 209} 210 211/* 212 * Called at splsched. 213 */ 214void 215ast_check( 216 processor_t processor) 217{ 218 thread_t thread = processor->active_thread; 219 220 processor->current_pri = thread->sched_pri; 221 processor->current_thmode = thread->sched_mode; 222 if ( processor->state == PROCESSOR_RUNNING || 223 processor->state == PROCESSOR_SHUTDOWN ) { 224 ast_t preempt; 225 226 /* 227 * Propagate thread ast to processor. 228 */ 229 pal_ast_check(thread); 230 231 ast_propagate(thread->ast); 232 233 /* 234 * Context switch check. 235 */ 236 if ((preempt = csw_check(processor)) != AST_NONE) 237 ast_on(preempt); 238 } 239} 240