|
|
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 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: * File: clock_prim.c ! 54: * Author: Avadis Tevanian, Jr. ! 55: * Date: 1986 ! 56: * ! 57: * Clock primitives. ! 58: */ ! 59: #include <cpus.h> ! 60: #include <stat_time.h> ! 61: #include <mach_prof.h> ! 62: #include <gprof.h> ! 63: ! 64: #include <mach/boolean.h> ! 65: #include <mach/machine.h> ! 66: #include <mach/time_value.h> ! 67: #include <mach/vm_param.h> ! 68: #include <mach/vm_prot.h> ! 69: #include <kern/clock.h> ! 70: #include <kern/counters.h> ! 71: #include <kern/cpu_number.h> ! 72: #include <kern/host.h> ! 73: #include <kern/lock.h> ! 74: #include <kern/mach_param.h> ! 75: #include <kern/misc_protos.h> ! 76: #include <kern/processor.h> ! 77: #include <kern/profile.h> ! 78: #include <kern/sched.h> ! 79: #include <kern/sched_prim.h> ! 80: #include <kern/spl.h> ! 81: #include <kern/thread.h> ! 82: #include <kern/thread_swap.h> ! 83: #include <kern/time_out.h> ! 84: #include <vm/vm_kern.h> /* kernel_map */ ! 85: #include <machine/mach_param.h> /* HZ */ ! 86: ! 87: #include <mach/clock_server.h> ! 88: #include <mach/clock_priv_server.h> ! 89: #include <mach/mach_host_server.h> ! 90: ! 91: #include <profiling/profile-mk.h> ! 92: ! 93: #if STAT_TIME ! 94: #define TICKBUMP(t) timer_bump(t, (1000000/HZ)) ! 95: #else ! 96: #define TICKBUMP(t) ! 97: #endif ! 98: ! 99: boolean_t profile_kernel_services = TRUE; /* Indicates wether or not we ! 100: * account kernel services ! 101: * samples for user task */ ! 102: ! 103: /* ! 104: * Hertz rate clock interrupt servicing. Primarily used to ! 105: * update CPU statistics, recompute thread priority, and to ! 106: * do profiling ! 107: */ ! 108: void ! 109: hertz_tick( ! 110: boolean_t usermode, /* executing user code */ ! 111: natural_t pc) ! 112: { ! 113: thread_act_t thr_act; ! 114: register int my_cpu; ! 115: register thread_t thread = current_thread(); ! 116: int state; ! 117: #if MACH_PROF ! 118: #ifdef __MACHO__ ! 119: #define ETEXT etext ! 120: extern long etext; ! 121: #else ! 122: #define ETEXT &etext ! 123: extern char etext; ! 124: #endif ! 125: boolean_t inkernel; ! 126: #endif /* MACH_PROF */ ! 127: #if GPROF ! 128: struct profile_vars *pv; ! 129: prof_uptrint_t s; ! 130: #endif ! 131: ! 132: #ifdef lint ! 133: pc++; ! 134: #endif /* lint */ ! 135: ! 136: mp_disable_preemption(); ! 137: my_cpu = cpu_number(); ! 138: ! 139: /* ! 140: * The system startup sequence initializes the clock ! 141: * before kicking off threads. So it's possible, ! 142: * especially when debugging, to wind up here with ! 143: * no thread to bill against. So ignore the tick. ! 144: */ ! 145: if (thread == THREAD_NULL) { ! 146: mp_enable_preemption(); ! 147: return; ! 148: } ! 149: ! 150: #if MACH_PROF ! 151: inkernel = !usermode && (pc < (unsigned int)ETEXT); ! 152: #endif /* MACH_PROF */ ! 153: ! 154: /* ! 155: * Hertz processing performed by all processors ! 156: * includes statistics gathering, state tracking, ! 157: * and quantum updating. ! 158: */ ! 159: counter(c_clock_ticks++); ! 160: ! 161: #if GPROF ! 162: pv = PROFILE_VARS(my_cpu); ! 163: #endif ! 164: ! 165: if (usermode) { ! 166: TICKBUMP(&thread->user_timer); ! 167: #if 0 ! 168: if (thread->priority < BASEPRI_USER) ! 169: state = CPU_STATE_NICE; ! 170: else ! 171: #endif ! 172: state = CPU_STATE_USER; ! 173: #if GPROF ! 174: if (pv->active) ! 175: PROF_CNT_INC(pv->stats.user_ticks); ! 176: #endif ! 177: } ! 178: else { ! 179: switch(processor_ptr[my_cpu]->state) { ! 180: ! 181: case PROCESSOR_IDLE: ! 182: TICKBUMP(&thread->system_timer); ! 183: state = CPU_STATE_IDLE; ! 184: break; ! 185: ! 186: default: ! 187: TICKBUMP(&thread->system_timer); ! 188: state = CPU_STATE_SYSTEM; ! 189: break; ! 190: } ! 191: #if GPROF ! 192: if (pv->active) { ! 193: if (state == CPU_STATE_SYSTEM) ! 194: PROF_CNT_INC(pv->stats.kernel_ticks); ! 195: else ! 196: PROF_CNT_INC(pv->stats.idle_ticks); ! 197: ! 198: if ((prof_uptrint_t)pc < _profile_vars.profil_info.lowpc) ! 199: PROF_CNT_INC(pv->stats.too_low); ! 200: else { ! 201: s = (prof_uptrint_t)pc - _profile_vars.profil_info.lowpc; ! 202: if (s < pv->profil_info.text_len) { ! 203: LHISTCOUNTER *ptr = (LHISTCOUNTER *) pv->profil_buf; ! 204: LPROF_CNT_INC(ptr[s / HISTFRACTION]); ! 205: } ! 206: else ! 207: PROF_CNT_INC(pv->stats.too_high); ! 208: } ! 209: } ! 210: #endif ! 211: } ! 212: ! 213: machine_slot[my_cpu].cpu_ticks[state]++; ! 214: thread_quantum_update(my_cpu, thread, 1, state); ! 215: ! 216: /* ! 217: * Hertz processing performed by the master-cpu ! 218: * exclusively. ! 219: */ ! 220: if (my_cpu == master_cpu) { ! 221: #ifdef MACH_BSD ! 222: { ! 223: extern void bsd_hardclock( ! 224: boolean_t usermode, ! 225: natural_t pc, ! 226: int ticks); ! 227: ! 228: bsd_hardclock(usermode, pc, 1); ! 229: } ! 230: #endif /* MACH_BSD */ ! 231: } ! 232: ! 233: #if MACH_PROF ! 234: thr_act = thread->top_act; ! 235: if (thr_act->act_profiled && thread->sched_pri != DEPRESSPRI) { ! 236: if (inkernel && thr_act->map != kernel_map) { ! 237: /* ! 238: * Non-kernel thread running in kernel ! 239: * Register user pc (mach_msg, vm_allocate ...) ! 240: */ ! 241: if (profile_kernel_services) ! 242: profile(user_pc(thr_act), thr_act->profil_buffer); ! 243: } ! 244: else ! 245: /* ! 246: * User thread and user mode or ! 247: * user (server) thread in kernel-loaded server or ! 248: * kernel thread and kernel mode ! 249: * register interrupted pc ! 250: */ ! 251: profile(pc, thr_act->profil_buffer); ! 252: } ! 253: if (kernel_task->task_profiled && thread->sched_pri != DEPRESSPRI) { ! 254: if (inkernel && thr_act->map != kernel_map) ! 255: /* ! 256: * User thread not profiled in kernel mode, ! 257: * kernel task profiled, register kernel pc ! 258: * for kernel task ! 259: */ ! 260: profile(pc, kernel_task->profil_buffer); ! 261: } ! 262: #endif /* MACH_PROF */ ! 263: mp_enable_preemption(); ! 264: } ! 265: ! 266: ! 267: /* ! 268: * Kernel timeout services. ! 269: */ ! 270: ! 271: /* ! 272: * Set a timeout. ! 273: * ! 274: * fcn: function to call ! 275: * param: parameter to pass to function ! 276: * interval: timeout interval, in hz. ! 277: */ ! 278: void ! 279: timeout( ! 280: timeout_fcn_t fcn, ! 281: void *param, ! 282: int interval) ! 283: { ! 284: AbsoluteTime deadline; ! 285: ! 286: clock_interval_to_deadline(interval, NSEC_PER_SEC / hz, &deadline); ! 287: thread_call_func_delayed((thread_call_func_t)fcn, param, deadline); ! 288: } ! 289: ! 290: /* ! 291: * Cancel a timeout. ! 292: */ ! 293: void ! 294: untimeout( ! 295: register timeout_fcn_t fcn, ! 296: register void *param) ! 297: { ! 298: thread_call_func_cancel((thread_call_func_t)fcn, param, FALSE); ! 299: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.