kern_clock.c revision 174070
11541Srgrimes/*- 21541Srgrimes * Copyright (c) 1982, 1986, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * (c) UNIX System Laboratories, Inc. 51541Srgrimes * All or some portions of this file are derived from material licensed 61541Srgrimes * to the University of California by American Telephone and Telegraph 71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 81541Srgrimes * the permission of UNIX System Laboratories, Inc. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 4. Neither the name of the University nor the names of its contributors 191541Srgrimes * may be used to endorse or promote products derived from this software 201541Srgrimes * without specific prior written permission. 211541Srgrimes * 221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321541Srgrimes * SUCH DAMAGE. 331541Srgrimes * 341541Srgrimes * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 351541Srgrimes */ 361541Srgrimes 37116182Sobrien#include <sys/cdefs.h> 38116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_clock.c 174070 2007-11-29 06:34:30Z peter $"); 39116182Sobrien 40170075Semaste#include "opt_kdb.h" 41150968Sglebius#include "opt_device_polling.h" 42147565Speter#include "opt_hwpmc_hooks.h" 4344666Sphk#include "opt_ntp.h" 44116874Ssmkelly#include "opt_watchdog.h" 4544666Sphk 461541Srgrimes#include <sys/param.h> 471541Srgrimes#include <sys/systm.h> 481541Srgrimes#include <sys/callout.h> 49131927Smarcel#include <sys/kdb.h> 501541Srgrimes#include <sys/kernel.h> 5174914Sjhb#include <sys/lock.h> 5284812Sjhb#include <sys/ktr.h> 5367365Sjhb#include <sys/mutex.h> 541541Srgrimes#include <sys/proc.h> 55111024Sjeff#include <sys/resource.h> 561541Srgrimes#include <sys/resourcevar.h> 57104964Sjeff#include <sys/sched.h> 583308Sphk#include <sys/signalvar.h> 5976078Sjhb#include <sys/smp.h> 602320Sdg#include <vm/vm.h> 6112662Sdg#include <vm/pmap.h> 6212662Sdg#include <vm/vm_map.h> 633308Sphk#include <sys/sysctl.h> 6467551Sjhb#include <sys/bus.h> 6567551Sjhb#include <sys/interrupt.h> 66114216Skan#include <sys/limits.h> 67102926Sphk#include <sys/timetc.h> 681541Srgrimes 691541Srgrimes#ifdef GPROF 701541Srgrimes#include <sys/gmon.h> 711541Srgrimes#endif 721541Srgrimes 73146799Sjkoshy#ifdef HWPMC_HOOKS 74146799Sjkoshy#include <sys/pmckern.h> 75146799Sjkoshy#endif 76146799Sjkoshy 7787902Sluigi#ifdef DEVICE_POLLING 7887902Sluigiextern void hardclock_device_poll(void); 7987902Sluigi#endif /* DEVICE_POLLING */ 8031639Sfsmp 8192723Salfredstatic void initclocks(void *dummy); 8210358SjulianSYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) 8310358Sjulian 84169803Sjeff/* Spin-lock protecting profiling statistics. */ 85170468Sattiliostatic struct mtx time_lock; 86169803Sjeff 87147692Speterstatic int 88147692Spetersysctl_kern_cp_time(SYSCTL_HANDLER_ARGS) 89147692Speter{ 90147692Speter int error; 91174070Speter long cp_time[CPUSTATES]; 92147703Sps#ifdef SCTL_MASK32 93147692Speter int i; 94147692Speter unsigned int cp_time32[CPUSTATES]; 95174070Speter#endif 96157822Sjhb 97174070Speter read_cpu_time(cp_time); 98174070Speter#ifdef SCTL_MASK32 99147703Sps if (req->flags & SCTL_MASK32) { 100147692Speter if (!req->oldptr) 101147692Speter return SYSCTL_OUT(req, 0, sizeof(cp_time32)); 102147692Speter for (i = 0; i < CPUSTATES; i++) 103147692Speter cp_time32[i] = (unsigned int)cp_time[i]; 104147692Speter error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32)); 105147692Speter } else 106147692Speter#endif 107147692Speter { 108147692Speter if (!req->oldptr) 109147692Speter return SYSCTL_OUT(req, 0, sizeof(cp_time)); 110147692Speter error = SYSCTL_OUT(req, cp_time, sizeof(cp_time)); 111147692Speter } 112147692Speter return error; 113147692Speter} 114147692Speter 115157822SjhbSYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD, 116147692Speter 0,0, sysctl_kern_cp_time, "LU", "CPU time statistics"); 117147692Speter 118174070Speterstatic long empty[CPUSTATES]; 119174070Speter 120174070Speterstatic int 121174070Spetersysctl_kern_cp_times(SYSCTL_HANDLER_ARGS) 122174070Speter{ 123174070Speter struct pcpu *pcpu; 124174070Speter int error; 125174070Speter int i, c; 126174070Speter long *cp_time; 127174070Speter#ifdef SCTL_MASK32 128174070Speter unsigned int cp_time32[CPUSTATES]; 129174070Speter#endif 130174070Speter 131174070Speter if (!req->oldptr) { 132174070Speter#ifdef SCTL_MASK32 133174070Speter if (req->flags & SCTL_MASK32) 134174070Speter return SYSCTL_OUT(req, 0, sizeof(cp_time32) * (mp_maxid + 1)); 135174070Speter else 136174070Speter#endif 137174070Speter return SYSCTL_OUT(req, 0, sizeof(long) * CPUSTATES * (mp_maxid + 1)); 138174070Speter } 139174070Speter for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) { 140174070Speter if (!CPU_ABSENT(c)) { 141174070Speter pcpu = pcpu_find(c); 142174070Speter cp_time = pcpu->pc_cp_time; 143174070Speter } else { 144174070Speter cp_time = empty; 145174070Speter } 146174070Speter#ifdef SCTL_MASK32 147174070Speter if (req->flags & SCTL_MASK32) { 148174070Speter for (i = 0; i < CPUSTATES; i++) 149174070Speter cp_time32[i] = (unsigned int)cp_time[i]; 150174070Speter error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32)); 151174070Speter } else 152174070Speter#endif 153174070Speter error = SYSCTL_OUT(req, cp_time, sizeof(long) * CPUSTATES); 154174070Speter } 155174070Speter return error; 156174070Speter} 157174070Speter 158174070SpeterSYSCTL_PROC(_kern, OID_AUTO, cp_times, CTLTYPE_LONG|CTLFLAG_RD, 159174070Speter 0,0, sysctl_kern_cp_times, "LU", "per-CPU time statistics"); 160174070Speter 161174070Spetervoid 162174070Speterread_cpu_time(long *cp_time) 163174070Speter{ 164174070Speter struct pcpu *pc; 165174070Speter int i, j; 166174070Speter 167174070Speter /* Sum up global cp_time[]. */ 168174070Speter bzero(cp_time, sizeof(long) * CPUSTATES); 169174070Speter for (i = 0; i <= mp_maxid; i++) { 170174070Speter if (CPU_ABSENT(i)) 171174070Speter continue; 172174070Speter pc = pcpu_find(i); 173174070Speter for (j = 0; j < CPUSTATES; j++) 174174070Speter cp_time[j] += pc->pc_cp_time[j]; 175174070Speter } 176174070Speter} 177174070Speter 178126383Sphk#ifdef SW_WATCHDOG 179126383Sphk#include <sys/watchdog.h> 180116874Ssmkelly 181126383Sphkstatic int watchdog_ticks; 182116874Ssmkellystatic int watchdog_enabled; 183126383Sphkstatic void watchdog_fire(void); 184126383Sphkstatic void watchdog_config(void *, u_int, int *); 185126383Sphk#endif /* SW_WATCHDOG */ 186116874Ssmkelly 1871541Srgrimes/* 1881541Srgrimes * Clock handling routines. 1891541Srgrimes * 19034618Sphk * This code is written to operate with two timers that run independently of 19134618Sphk * each other. 19233690Sphk * 19334618Sphk * The main timer, running hz times per second, is used to trigger interval 19434618Sphk * timers, timeouts and rescheduling as needed. 19533690Sphk * 19634618Sphk * The second timer handles kernel and user profiling, 19734618Sphk * and does resource use estimation. If the second timer is programmable, 19834618Sphk * it is randomized to avoid aliasing between the two clocks. For example, 19934618Sphk * the randomization prevents an adversary from always giving up the cpu 2001541Srgrimes * just before its quantum expires. Otherwise, it would never accumulate 2011541Srgrimes * cpu ticks. The mean frequency of the second timer is stathz. 20234618Sphk * 20334618Sphk * If no second timer exists, stathz will be zero; in this case we drive 20434618Sphk * profiling and statistics off the main clock. This WILL NOT be accurate; 20534618Sphk * do not do it unless absolutely necessary. 20634618Sphk * 2071541Srgrimes * The statistics clock may (or may not) be run at a higher rate while 20834618Sphk * profiling. This profile clock runs at profhz. We require that profhz 20934618Sphk * be an integral multiple of stathz. 2101541Srgrimes * 21134618Sphk * If the statistics clock is running fast, it must be divided by the ratio 21234618Sphk * profhz/stathz for statistics. (For profiling, every tick counts.) 21334618Sphk * 21433690Sphk * Time-of-day is maintained using a "timecounter", which may or may 21533690Sphk * not be related to the hardware generating the above mentioned 21633690Sphk * interrupts. 2171541Srgrimes */ 2181541Srgrimes 2191541Srgrimesint stathz; 2201541Srgrimesint profhz; 221110296Sjakeint profprocs; 2221541Srgrimesint ticks; 223110296Sjakeint psratio; 2241541Srgrimes 2251541Srgrimes/* 2261541Srgrimes * Initialize clock frequencies and start both clocks running. 2271541Srgrimes */ 22810358Sjulian/* ARGSUSED*/ 22910358Sjulianstatic void 23012569Sbdeinitclocks(dummy) 23112569Sbde void *dummy; 2321541Srgrimes{ 2331541Srgrimes register int i; 2341541Srgrimes 2351541Srgrimes /* 2361541Srgrimes * Set divisors to 1 (normal case) and let the machine-specific 2371541Srgrimes * code do its bit. 2381541Srgrimes */ 239169906Srwatson mtx_init(&time_lock, "time lock", NULL, MTX_SPIN); 2401541Srgrimes cpu_initclocks(); 2411541Srgrimes 2421541Srgrimes /* 2431541Srgrimes * Compute profhz/stathz, and fix profhz if needed. 2441541Srgrimes */ 2451541Srgrimes i = stathz ? stathz : hz; 2461541Srgrimes if (profhz == 0) 2471541Srgrimes profhz = i; 2481541Srgrimes psratio = profhz / i; 249126383Sphk#ifdef SW_WATCHDOG 250126383Sphk EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0); 251126383Sphk#endif 2521541Srgrimes} 2531541Srgrimes 2541541Srgrimes/* 255110296Sjake * Each time the real-time timer fires, this function is called on all CPUs. 256153666Sjhb * Note that hardclock() calls hardclock_cpu() for the boot CPU, so only 257110296Sjake * the other CPUs in the system need to call this function. 25876078Sjhb */ 25976078Sjhbvoid 260153666Sjhbhardclock_cpu(int usermode) 26176078Sjhb{ 26276078Sjhb struct pstats *pstats; 263110296Sjake struct thread *td = curthread; 26483366Sjulian struct proc *p = td->td_proc; 265172207Sjeff int flags; 26676078Sjhb 26776078Sjhb /* 26876078Sjhb * Run current process's virtual and profile time, as needed. 26976078Sjhb */ 270163709Sjb pstats = p->p_stats; 271172207Sjeff flags = 0; 272163709Sjb if (usermode && 273170297Sjeff timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value)) { 274170297Sjeff PROC_SLOCK(p); 275172207Sjeff if (itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) 276172207Sjeff flags |= TDF_ALRMPEND | TDF_ASTPENDING; 277170297Sjeff PROC_SUNLOCK(p); 278163709Sjb } 279170297Sjeff if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value)) { 280170297Sjeff PROC_SLOCK(p); 281172207Sjeff if (itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) 282172207Sjeff flags |= TDF_PROFPEND | TDF_ASTPENDING; 283170297Sjeff PROC_SUNLOCK(p); 284170297Sjeff } 285170297Sjeff thread_lock(td); 286170297Sjeff sched_tick(); 287172207Sjeff td->td_flags |= flags; 288170297Sjeff thread_unlock(td); 289146799Sjkoshy 290146799Sjkoshy#ifdef HWPMC_HOOKS 291146799Sjkoshy if (PMC_CPU_HAS_SAMPLES(PCPU_GET(cpuid))) 292146799Sjkoshy PMC_CALL_HOOK_UNLOCKED(curthread, PMC_FN_DO_SAMPLES, NULL); 293146799Sjkoshy#endif 29476078Sjhb} 29576078Sjhb 29676078Sjhb/* 2971541Srgrimes * The real-time timer, interrupting hz times per second. 2981541Srgrimes */ 2991541Srgrimesvoid 300153666Sjhbhardclock(int usermode, uintfptr_t pc) 3011541Srgrimes{ 30268889Sjake int need_softclock = 0; 3031541Srgrimes 304153666Sjhb hardclock_cpu(usermode); 3051541Srgrimes 306102926Sphk tc_ticktock(); 3071541Srgrimes /* 3081541Srgrimes * If no separate statistics clock is available, run it from here. 30976078Sjhb * 31076078Sjhb * XXX: this only works for UP 3111541Srgrimes */ 312110296Sjake if (stathz == 0) { 313153666Sjhb profclock(usermode, pc); 314153666Sjhb statclock(usermode); 315110296Sjake } 3161541Srgrimes 31787902Sluigi#ifdef DEVICE_POLLING 31890550Sluigi hardclock_device_poll(); /* this is very short and quick */ 31987902Sluigi#endif /* DEVICE_POLLING */ 3202858Swollman 32134618Sphk /* 32234618Sphk * Process callouts at a very low cpu priority, so we don't keep the 32334618Sphk * relatively high clock interrupt priority any longer than necessary. 32434618Sphk */ 32586423Sjhb mtx_lock_spin_flags(&callout_lock, MTX_QUIET); 32668889Sjake ticks++; 327159598Sdelphij if (!TAILQ_EMPTY(&callwheel[ticks & callwheelmask])) { 32868889Sjake need_softclock = 1; 32934618Sphk } else if (softticks + 1 == ticks) 33034618Sphk ++softticks; 33186423Sjhb mtx_unlock_spin_flags(&callout_lock, MTX_QUIET); 33268889Sjake 33368889Sjake /* 334170297Sjeff * swi_sched acquires the thread lock, so we don't want to call it 335170297Sjeff * with callout_lock held; incorrect locking order. 33668889Sjake */ 33768889Sjake if (need_softclock) 33888900Sjhb swi_sched(softclock_ih, 0); 339116874Ssmkelly 340126383Sphk#ifdef SW_WATCHDOG 341126383Sphk if (watchdog_enabled > 0 && --watchdog_ticks <= 0) 342116874Ssmkelly watchdog_fire(); 343126383Sphk#endif /* SW_WATCHDOG */ 3441541Srgrimes} 3451541Srgrimes 3461541Srgrimes/* 34734961Sphk * Compute number of ticks in the specified amount of time. 3481541Srgrimes */ 3491541Srgrimesint 35034961Sphktvtohz(tv) 3511541Srgrimes struct timeval *tv; 3521541Srgrimes{ 3535081Sbde register unsigned long ticks; 3545081Sbde register long sec, usec; 3551541Srgrimes 3561541Srgrimes /* 3575081Sbde * If the number of usecs in the whole seconds part of the time 3585081Sbde * difference fits in a long, then the total number of usecs will 3595081Sbde * fit in an unsigned long. Compute the total and convert it to 3605081Sbde * ticks, rounding up and adding 1 to allow for the current tick 3615081Sbde * to expire. Rounding also depends on unsigned long arithmetic 3625081Sbde * to avoid overflow. 3631541Srgrimes * 3645081Sbde * Otherwise, if the number of ticks in the whole seconds part of 3655081Sbde * the time difference fits in a long, then convert the parts to 3665081Sbde * ticks separately and add, using similar rounding methods and 3675081Sbde * overflow avoidance. This method would work in the previous 3685081Sbde * case but it is slightly slower and assumes that hz is integral. 3695081Sbde * 3705081Sbde * Otherwise, round the time difference down to the maximum 3715081Sbde * representable value. 3725081Sbde * 3735081Sbde * If ints have 32 bits, then the maximum value for any timeout in 3745081Sbde * 10ms ticks is 248 days. 3751541Srgrimes */ 37634961Sphk sec = tv->tv_sec; 37734961Sphk usec = tv->tv_usec; 3785081Sbde if (usec < 0) { 3795081Sbde sec--; 3805081Sbde usec += 1000000; 3815081Sbde } 3825081Sbde if (sec < 0) { 3835081Sbde#ifdef DIAGNOSTIC 38434618Sphk if (usec > 0) { 38533690Sphk sec++; 38633690Sphk usec -= 1000000; 38733690Sphk } 38834961Sphk printf("tvotohz: negative time difference %ld sec %ld usec\n", 3895081Sbde sec, usec); 3905081Sbde#endif 3915081Sbde ticks = 1; 3925081Sbde } else if (sec <= LONG_MAX / 1000000) 3935081Sbde ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1)) 3945081Sbde / tick + 1; 3955081Sbde else if (sec <= LONG_MAX / hz) 3965081Sbde ticks = sec * hz 3975081Sbde + ((unsigned long)usec + (tick - 1)) / tick + 1; 3981541Srgrimes else 3995081Sbde ticks = LONG_MAX; 4005081Sbde if (ticks > INT_MAX) 4015081Sbde ticks = INT_MAX; 40240012Salex return ((int)ticks); 4031541Srgrimes} 4041541Srgrimes 4051541Srgrimes/* 4061541Srgrimes * Start profiling on a process. 4071541Srgrimes * 4081541Srgrimes * Kernel profiling passes proc0 which never exits and hence 4091541Srgrimes * keeps the profile clock running constantly. 4101541Srgrimes */ 4111541Srgrimesvoid 4121541Srgrimesstartprofclock(p) 4131541Srgrimes register struct proc *p; 4141541Srgrimes{ 4151541Srgrimes 416113874Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 417113874Sjhb if (p->p_flag & P_STOPPROF) 418110530Sjulian return; 419113874Sjhb if ((p->p_flag & P_PROFIL) == 0) { 420113874Sjhb p->p_flag |= P_PROFIL; 421169803Sjeff mtx_lock_spin(&time_lock); 422110296Sjake if (++profprocs == 1) 423110296Sjake cpu_startprofclock(); 424169803Sjeff mtx_unlock_spin(&time_lock); 4251541Srgrimes } 4261541Srgrimes} 4271541Srgrimes 4281541Srgrimes/* 4291541Srgrimes * Stop profiling on a process. 4301541Srgrimes */ 4311541Srgrimesvoid 4321541Srgrimesstopprofclock(p) 4331541Srgrimes register struct proc *p; 4341541Srgrimes{ 4351541Srgrimes 436110530Sjulian PROC_LOCK_ASSERT(p, MA_OWNED); 437113874Sjhb if (p->p_flag & P_PROFIL) { 438113874Sjhb if (p->p_profthreads != 0) { 439113874Sjhb p->p_flag |= P_STOPPROF; 440113874Sjhb while (p->p_profthreads != 0) 441113874Sjhb msleep(&p->p_profthreads, &p->p_mtx, PPAUSE, 442123740Speter "stopprof", 0); 443113874Sjhb p->p_flag &= ~P_STOPPROF; 444110530Sjulian } 445128852Scperciva if ((p->p_flag & P_PROFIL) == 0) 446128852Scperciva return; 447113874Sjhb p->p_flag &= ~P_PROFIL; 448169803Sjeff mtx_lock_spin(&time_lock); 449110296Sjake if (--profprocs == 0) 450110296Sjake cpu_stopprofclock(); 451169803Sjeff mtx_unlock_spin(&time_lock); 4521541Srgrimes } 4531541Srgrimes} 4541541Srgrimes 4551541Srgrimes/* 456170174Sjeff * Statistics clock. Updates rusage information and calls the scheduler 457170174Sjeff * to adjust priorities of the active thread. 458170174Sjeff * 459110296Sjake * This should be called by all active processors. 4601541Srgrimes */ 4611541Srgrimesvoid 462153666Sjhbstatclock(int usermode) 4631541Srgrimes{ 46417342Sbde struct rusage *ru; 46517342Sbde struct vmspace *vm; 466110296Sjake struct thread *td; 467110296Sjake struct proc *p; 468110296Sjake long rss; 469174070Speter long *cp_time; 4701541Srgrimes 471110296Sjake td = curthread; 472110296Sjake p = td->td_proc; 473110296Sjake 474174070Speter cp_time = (long *)PCPU_PTR(cp_time); 475153666Sjhb if (usermode) { 47653751Sbde /* 47753751Sbde * Charge the time as appropriate. 4781541Srgrimes */ 479163709Sjb#ifdef KSE 480116361Sdavidxu if (p->p_flag & P_SA) 481111028Sjeff thread_statclock(1); 482163709Sjb#endif 483155534Sphk td->td_uticks++; 484130551Sjulian if (p->p_nice > NZERO) 485174070Speter cp_time[CP_NICE]++; 4861541Srgrimes else 487174070Speter cp_time[CP_USER]++; 4881541Srgrimes } else { 4891541Srgrimes /* 4901541Srgrimes * Came from kernel mode, so we were: 4911541Srgrimes * - handling an interrupt, 4921541Srgrimes * - doing syscall or trap work on behalf of the current 4931541Srgrimes * user process, or 4941541Srgrimes * - spinning in the idle loop. 4951541Srgrimes * Whichever it is, charge the time as appropriate. 4961541Srgrimes * Note that we charge interrupts to the current process, 4971541Srgrimes * regardless of whether they are ``for'' that process, 4981541Srgrimes * so that we know how much of its real time was spent 4991541Srgrimes * in ``non-process'' (i.e., interrupt) work. 5001541Srgrimes */ 501151658Sjhb if ((td->td_pflags & TDP_ITHREAD) || 502151658Sjhb td->td_intr_nesting_level >= 2) { 503155534Sphk td->td_iticks++; 504174070Speter cp_time[CP_INTR]++; 50565557Sjasone } else { 506163709Sjb#ifdef KSE 507116361Sdavidxu if (p->p_flag & P_SA) 508111028Sjeff thread_statclock(0); 509163709Sjb#endif 510155455Sphk td->td_pticks++; 511155534Sphk td->td_sticks++; 512167327Sjulian if (!TD_IS_IDLETHREAD(td)) 513174070Speter cp_time[CP_SYS]++; 51465557Sjasone else 515174070Speter cp_time[CP_IDLE]++; 51665557Sjasone } 5171541Srgrimes } 5181541Srgrimes 51965782Sjhb /* Update resource usage integrals and maximums. */ 520131436Sjhb MPASS(p->p_vmspace != NULL); 521131436Sjhb vm = p->p_vmspace; 522170174Sjeff ru = &td->td_ru; 523131436Sjhb ru->ru_ixrss += pgtok(vm->vm_tsize); 524131436Sjhb ru->ru_idrss += pgtok(vm->vm_dsize); 525131436Sjhb ru->ru_isrss += pgtok(vm->vm_ssize); 526131436Sjhb rss = pgtok(vmspace_resident_count(vm)); 527131436Sjhb if (ru->ru_maxrss < rss) 528131436Sjhb ru->ru_maxrss = rss; 529170297Sjeff CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d", 530173600Sjulian td, td->td_name, td->td_priority, (stathz)?stathz:hz); 531174070Speter thread_lock_flags(td, MTX_QUIET); 532170297Sjeff sched_clock(td); 533170297Sjeff thread_unlock(td); 53476078Sjhb} 53566716Sjhb 53676078Sjhbvoid 537153666Sjhbprofclock(int usermode, uintfptr_t pc) 53876078Sjhb{ 539110296Sjake struct thread *td; 540110296Sjake#ifdef GPROF 541110296Sjake struct gmonparam *g; 542153490Sjhb uintfptr_t i; 543110296Sjake#endif 54476078Sjhb 545111032Sjulian td = curthread; 546153666Sjhb if (usermode) { 547110296Sjake /* 548110296Sjake * Came from user mode; CPU was in user state. 549110296Sjake * If this process is being profiled, record the tick. 550110530Sjulian * if there is no related user location yet, don't 551110530Sjulian * bother trying to count it. 552110296Sjake */ 553113874Sjhb if (td->td_proc->p_flag & P_PROFIL) 554153666Sjhb addupc_intr(td, pc, 1); 555110296Sjake } 556110296Sjake#ifdef GPROF 557110296Sjake else { 558110296Sjake /* 559110296Sjake * Kernel statistics are just like addupc_intr, only easier. 560110296Sjake */ 561110296Sjake g = &_gmonparam; 562153666Sjhb if (g->state == GMON_PROF_ON && pc >= g->lowpc) { 563153666Sjhb i = PC_TO_I(g, pc); 564110296Sjake if (i < g->textsize) { 565153666Sjhb KCOUNT(g, i)++; 566110296Sjake } 567110296Sjake } 568110296Sjake } 569110296Sjake#endif 5701541Srgrimes} 5711541Srgrimes 5721541Srgrimes/* 5731541Srgrimes * Return information about system clocks. 5741541Srgrimes */ 57512152Sphkstatic int 57662573Sphksysctl_kern_clockrate(SYSCTL_HANDLER_ARGS) 5771541Srgrimes{ 5781541Srgrimes struct clockinfo clkinfo; 5791541Srgrimes /* 5801541Srgrimes * Construct clockinfo structure. 5811541Srgrimes */ 58296052Sbde bzero(&clkinfo, sizeof(clkinfo)); 5831541Srgrimes clkinfo.hz = hz; 5841541Srgrimes clkinfo.tick = tick; 5851541Srgrimes clkinfo.profhz = profhz; 5861541Srgrimes clkinfo.stathz = stathz ? stathz : hz; 58712243Sphk return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req)); 5881541Srgrimes} 5892858Swollman 59012623SphkSYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD, 59188019Sluigi 0, 0, sysctl_kern_clockrate, "S,clockinfo", 59288019Sluigi "Rate and period of various kernel clocks"); 593116874Ssmkelly 594126383Sphk#ifdef SW_WATCHDOG 595126383Sphk 596126383Sphkstatic void 597165260Sn_hibmawatchdog_config(void *unused __unused, u_int cmd, int *error) 598116874Ssmkelly{ 599126383Sphk u_int u; 600116874Ssmkelly 601126386Sphk u = cmd & WD_INTERVAL; 602165260Sn_hibma if (u >= WD_TO_1SEC) { 603126383Sphk watchdog_ticks = (1 << (u - WD_TO_1SEC)) * hz; 604126383Sphk watchdog_enabled = 1; 605165260Sn_hibma *error = 0; 606126383Sphk } else { 607126383Sphk watchdog_enabled = 0; 608126383Sphk } 609116874Ssmkelly} 610116874Ssmkelly 611116874Ssmkelly/* 612116874Ssmkelly * Handle a watchdog timeout by dumping interrupt information and 613170075Semaste * then either dropping to DDB or panicking. 614116874Ssmkelly */ 615116874Ssmkellystatic void 616116874Ssmkellywatchdog_fire(void) 617116874Ssmkelly{ 618116874Ssmkelly int nintr; 619116874Ssmkelly u_int64_t inttotal; 620116874Ssmkelly u_long *curintr; 621116874Ssmkelly char *curname; 622116874Ssmkelly 623116874Ssmkelly curintr = intrcnt; 624116874Ssmkelly curname = intrnames; 625116874Ssmkelly inttotal = 0; 626116874Ssmkelly nintr = eintrcnt - intrcnt; 627157822Sjhb 628116874Ssmkelly printf("interrupt total\n"); 629116874Ssmkelly while (--nintr >= 0) { 630116874Ssmkelly if (*curintr) 631116874Ssmkelly printf("%-12s %20lu\n", curname, *curintr); 632116874Ssmkelly curname += strlen(curname) + 1; 633116874Ssmkelly inttotal += *curintr++; 634116874Ssmkelly } 635116908Ssmkelly printf("Total %20ju\n", (uintmax_t)inttotal); 636170075Semaste 637170075Semaste#if defined(KDB) && !defined(KDB_UNATTENDED) 638170075Semaste kdb_backtrace(); 639170075Semaste kdb_enter("watchdog timeout"); 640170075Semaste#else 641116874Ssmkelly panic("watchdog timeout"); 642170075Semaste#endif 643116874Ssmkelly} 644116874Ssmkelly 645126383Sphk#endif /* SW_WATCHDOG */ 646