kern_clock.c revision 174898
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 174898 2007-12-25 17:52:02Z rwatson $"); 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; 125174072Srwatson int c; 126174070Speter long *cp_time; 127174070Speter#ifdef SCTL_MASK32 128174070Speter unsigned int cp_time32[CPUSTATES]; 129174072Srwatson int i; 130174070Speter#endif 131174070Speter 132174070Speter if (!req->oldptr) { 133174070Speter#ifdef SCTL_MASK32 134174070Speter if (req->flags & SCTL_MASK32) 135174070Speter return SYSCTL_OUT(req, 0, sizeof(cp_time32) * (mp_maxid + 1)); 136174070Speter else 137174070Speter#endif 138174070Speter return SYSCTL_OUT(req, 0, sizeof(long) * CPUSTATES * (mp_maxid + 1)); 139174070Speter } 140174070Speter for (error = 0, c = 0; error == 0 && c <= mp_maxid; c++) { 141174070Speter if (!CPU_ABSENT(c)) { 142174070Speter pcpu = pcpu_find(c); 143174070Speter cp_time = pcpu->pc_cp_time; 144174070Speter } else { 145174070Speter cp_time = empty; 146174070Speter } 147174070Speter#ifdef SCTL_MASK32 148174070Speter if (req->flags & SCTL_MASK32) { 149174070Speter for (i = 0; i < CPUSTATES; i++) 150174070Speter cp_time32[i] = (unsigned int)cp_time[i]; 151174070Speter error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32)); 152174070Speter } else 153174070Speter#endif 154174070Speter error = SYSCTL_OUT(req, cp_time, sizeof(long) * CPUSTATES); 155174070Speter } 156174070Speter return error; 157174070Speter} 158174070Speter 159174070SpeterSYSCTL_PROC(_kern, OID_AUTO, cp_times, CTLTYPE_LONG|CTLFLAG_RD, 160174070Speter 0,0, sysctl_kern_cp_times, "LU", "per-CPU time statistics"); 161174070Speter 162174070Spetervoid 163174070Speterread_cpu_time(long *cp_time) 164174070Speter{ 165174070Speter struct pcpu *pc; 166174070Speter int i, j; 167174070Speter 168174070Speter /* Sum up global cp_time[]. */ 169174070Speter bzero(cp_time, sizeof(long) * CPUSTATES); 170174070Speter for (i = 0; i <= mp_maxid; i++) { 171174070Speter if (CPU_ABSENT(i)) 172174070Speter continue; 173174070Speter pc = pcpu_find(i); 174174070Speter for (j = 0; j < CPUSTATES; j++) 175174070Speter cp_time[j] += pc->pc_cp_time[j]; 176174070Speter } 177174070Speter} 178174070Speter 179126383Sphk#ifdef SW_WATCHDOG 180126383Sphk#include <sys/watchdog.h> 181116874Ssmkelly 182126383Sphkstatic int watchdog_ticks; 183116874Ssmkellystatic int watchdog_enabled; 184126383Sphkstatic void watchdog_fire(void); 185126383Sphkstatic void watchdog_config(void *, u_int, int *); 186126383Sphk#endif /* SW_WATCHDOG */ 187116874Ssmkelly 1881541Srgrimes/* 1891541Srgrimes * Clock handling routines. 1901541Srgrimes * 19134618Sphk * This code is written to operate with two timers that run independently of 19234618Sphk * each other. 19333690Sphk * 19434618Sphk * The main timer, running hz times per second, is used to trigger interval 19534618Sphk * timers, timeouts and rescheduling as needed. 19633690Sphk * 19734618Sphk * The second timer handles kernel and user profiling, 19834618Sphk * and does resource use estimation. If the second timer is programmable, 19934618Sphk * it is randomized to avoid aliasing between the two clocks. For example, 20034618Sphk * the randomization prevents an adversary from always giving up the cpu 2011541Srgrimes * just before its quantum expires. Otherwise, it would never accumulate 2021541Srgrimes * cpu ticks. The mean frequency of the second timer is stathz. 20334618Sphk * 20434618Sphk * If no second timer exists, stathz will be zero; in this case we drive 20534618Sphk * profiling and statistics off the main clock. This WILL NOT be accurate; 20634618Sphk * do not do it unless absolutely necessary. 20734618Sphk * 2081541Srgrimes * The statistics clock may (or may not) be run at a higher rate while 20934618Sphk * profiling. This profile clock runs at profhz. We require that profhz 21034618Sphk * be an integral multiple of stathz. 2111541Srgrimes * 21234618Sphk * If the statistics clock is running fast, it must be divided by the ratio 21334618Sphk * profhz/stathz for statistics. (For profiling, every tick counts.) 21434618Sphk * 21533690Sphk * Time-of-day is maintained using a "timecounter", which may or may 21633690Sphk * not be related to the hardware generating the above mentioned 21733690Sphk * interrupts. 2181541Srgrimes */ 2191541Srgrimes 2201541Srgrimesint stathz; 2211541Srgrimesint profhz; 222110296Sjakeint profprocs; 2231541Srgrimesint ticks; 224110296Sjakeint psratio; 2251541Srgrimes 2261541Srgrimes/* 2271541Srgrimes * Initialize clock frequencies and start both clocks running. 2281541Srgrimes */ 22910358Sjulian/* ARGSUSED*/ 23010358Sjulianstatic void 23112569Sbdeinitclocks(dummy) 23212569Sbde void *dummy; 2331541Srgrimes{ 2341541Srgrimes register int i; 2351541Srgrimes 2361541Srgrimes /* 2371541Srgrimes * Set divisors to 1 (normal case) and let the machine-specific 2381541Srgrimes * code do its bit. 2391541Srgrimes */ 240169906Srwatson mtx_init(&time_lock, "time lock", NULL, MTX_SPIN); 2411541Srgrimes cpu_initclocks(); 2421541Srgrimes 2431541Srgrimes /* 2441541Srgrimes * Compute profhz/stathz, and fix profhz if needed. 2451541Srgrimes */ 2461541Srgrimes i = stathz ? stathz : hz; 2471541Srgrimes if (profhz == 0) 2481541Srgrimes profhz = i; 2491541Srgrimes psratio = profhz / i; 250126383Sphk#ifdef SW_WATCHDOG 251126383Sphk EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0); 252126383Sphk#endif 2531541Srgrimes} 2541541Srgrimes 2551541Srgrimes/* 256110296Sjake * Each time the real-time timer fires, this function is called on all CPUs. 257153666Sjhb * Note that hardclock() calls hardclock_cpu() for the boot CPU, so only 258110296Sjake * the other CPUs in the system need to call this function. 25976078Sjhb */ 26076078Sjhbvoid 261153666Sjhbhardclock_cpu(int usermode) 26276078Sjhb{ 26376078Sjhb struct pstats *pstats; 264110296Sjake struct thread *td = curthread; 26583366Sjulian struct proc *p = td->td_proc; 266172207Sjeff int flags; 26776078Sjhb 26876078Sjhb /* 26976078Sjhb * Run current process's virtual and profile time, as needed. 27076078Sjhb */ 271163709Sjb pstats = p->p_stats; 272172207Sjeff flags = 0; 273163709Sjb if (usermode && 274170297Sjeff timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value)) { 275170297Sjeff PROC_SLOCK(p); 276172207Sjeff if (itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) 277172207Sjeff flags |= TDF_ALRMPEND | TDF_ASTPENDING; 278170297Sjeff PROC_SUNLOCK(p); 279163709Sjb } 280170297Sjeff if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value)) { 281170297Sjeff PROC_SLOCK(p); 282172207Sjeff if (itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) 283172207Sjeff flags |= TDF_PROFPEND | TDF_ASTPENDING; 284170297Sjeff PROC_SUNLOCK(p); 285170297Sjeff } 286170297Sjeff thread_lock(td); 287170297Sjeff sched_tick(); 288172207Sjeff td->td_flags |= flags; 289170297Sjeff thread_unlock(td); 290146799Sjkoshy 291146799Sjkoshy#ifdef HWPMC_HOOKS 292146799Sjkoshy if (PMC_CPU_HAS_SAMPLES(PCPU_GET(cpuid))) 293146799Sjkoshy PMC_CALL_HOOK_UNLOCKED(curthread, PMC_FN_DO_SAMPLES, NULL); 294146799Sjkoshy#endif 29576078Sjhb} 29676078Sjhb 29776078Sjhb/* 2981541Srgrimes * The real-time timer, interrupting hz times per second. 2991541Srgrimes */ 3001541Srgrimesvoid 301153666Sjhbhardclock(int usermode, uintfptr_t pc) 3021541Srgrimes{ 30368889Sjake int need_softclock = 0; 3041541Srgrimes 305153666Sjhb hardclock_cpu(usermode); 3061541Srgrimes 307102926Sphk tc_ticktock(); 3081541Srgrimes /* 3091541Srgrimes * If no separate statistics clock is available, run it from here. 31076078Sjhb * 31176078Sjhb * XXX: this only works for UP 3121541Srgrimes */ 313110296Sjake if (stathz == 0) { 314153666Sjhb profclock(usermode, pc); 315153666Sjhb statclock(usermode); 316110296Sjake } 3171541Srgrimes 31887902Sluigi#ifdef DEVICE_POLLING 31990550Sluigi hardclock_device_poll(); /* this is very short and quick */ 32087902Sluigi#endif /* DEVICE_POLLING */ 3212858Swollman 32234618Sphk /* 32334618Sphk * Process callouts at a very low cpu priority, so we don't keep the 32434618Sphk * relatively high clock interrupt priority any longer than necessary. 32534618Sphk */ 32686423Sjhb mtx_lock_spin_flags(&callout_lock, MTX_QUIET); 32768889Sjake ticks++; 328159598Sdelphij if (!TAILQ_EMPTY(&callwheel[ticks & callwheelmask])) { 32968889Sjake need_softclock = 1; 33034618Sphk } else if (softticks + 1 == ticks) 33134618Sphk ++softticks; 33286423Sjhb mtx_unlock_spin_flags(&callout_lock, MTX_QUIET); 33368889Sjake 33468889Sjake /* 335170297Sjeff * swi_sched acquires the thread lock, so we don't want to call it 336170297Sjeff * with callout_lock held; incorrect locking order. 33768889Sjake */ 33868889Sjake if (need_softclock) 33988900Sjhb swi_sched(softclock_ih, 0); 340116874Ssmkelly 341126383Sphk#ifdef SW_WATCHDOG 342126383Sphk if (watchdog_enabled > 0 && --watchdog_ticks <= 0) 343116874Ssmkelly watchdog_fire(); 344126383Sphk#endif /* SW_WATCHDOG */ 3451541Srgrimes} 3461541Srgrimes 3471541Srgrimes/* 34834961Sphk * Compute number of ticks in the specified amount of time. 3491541Srgrimes */ 3501541Srgrimesint 35134961Sphktvtohz(tv) 3521541Srgrimes struct timeval *tv; 3531541Srgrimes{ 3545081Sbde register unsigned long ticks; 3555081Sbde register long sec, usec; 3561541Srgrimes 3571541Srgrimes /* 3585081Sbde * If the number of usecs in the whole seconds part of the time 3595081Sbde * difference fits in a long, then the total number of usecs will 3605081Sbde * fit in an unsigned long. Compute the total and convert it to 3615081Sbde * ticks, rounding up and adding 1 to allow for the current tick 3625081Sbde * to expire. Rounding also depends on unsigned long arithmetic 3635081Sbde * to avoid overflow. 3641541Srgrimes * 3655081Sbde * Otherwise, if the number of ticks in the whole seconds part of 3665081Sbde * the time difference fits in a long, then convert the parts to 3675081Sbde * ticks separately and add, using similar rounding methods and 3685081Sbde * overflow avoidance. This method would work in the previous 3695081Sbde * case but it is slightly slower and assumes that hz is integral. 3705081Sbde * 3715081Sbde * Otherwise, round the time difference down to the maximum 3725081Sbde * representable value. 3735081Sbde * 3745081Sbde * If ints have 32 bits, then the maximum value for any timeout in 3755081Sbde * 10ms ticks is 248 days. 3761541Srgrimes */ 37734961Sphk sec = tv->tv_sec; 37834961Sphk usec = tv->tv_usec; 3795081Sbde if (usec < 0) { 3805081Sbde sec--; 3815081Sbde usec += 1000000; 3825081Sbde } 3835081Sbde if (sec < 0) { 3845081Sbde#ifdef DIAGNOSTIC 38534618Sphk if (usec > 0) { 38633690Sphk sec++; 38733690Sphk usec -= 1000000; 38833690Sphk } 38934961Sphk printf("tvotohz: negative time difference %ld sec %ld usec\n", 3905081Sbde sec, usec); 3915081Sbde#endif 3925081Sbde ticks = 1; 3935081Sbde } else if (sec <= LONG_MAX / 1000000) 3945081Sbde ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1)) 3955081Sbde / tick + 1; 3965081Sbde else if (sec <= LONG_MAX / hz) 3975081Sbde ticks = sec * hz 3985081Sbde + ((unsigned long)usec + (tick - 1)) / tick + 1; 3991541Srgrimes else 4005081Sbde ticks = LONG_MAX; 4015081Sbde if (ticks > INT_MAX) 4025081Sbde ticks = INT_MAX; 40340012Salex return ((int)ticks); 4041541Srgrimes} 4051541Srgrimes 4061541Srgrimes/* 4071541Srgrimes * Start profiling on a process. 4081541Srgrimes * 4091541Srgrimes * Kernel profiling passes proc0 which never exits and hence 4101541Srgrimes * keeps the profile clock running constantly. 4111541Srgrimes */ 4121541Srgrimesvoid 4131541Srgrimesstartprofclock(p) 4141541Srgrimes register struct proc *p; 4151541Srgrimes{ 4161541Srgrimes 417113874Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 418113874Sjhb if (p->p_flag & P_STOPPROF) 419110530Sjulian return; 420113874Sjhb if ((p->p_flag & P_PROFIL) == 0) { 421113874Sjhb p->p_flag |= P_PROFIL; 422169803Sjeff mtx_lock_spin(&time_lock); 423110296Sjake if (++profprocs == 1) 424110296Sjake cpu_startprofclock(); 425169803Sjeff mtx_unlock_spin(&time_lock); 4261541Srgrimes } 4271541Srgrimes} 4281541Srgrimes 4291541Srgrimes/* 4301541Srgrimes * Stop profiling on a process. 4311541Srgrimes */ 4321541Srgrimesvoid 4331541Srgrimesstopprofclock(p) 4341541Srgrimes register struct proc *p; 4351541Srgrimes{ 4361541Srgrimes 437110530Sjulian PROC_LOCK_ASSERT(p, MA_OWNED); 438113874Sjhb if (p->p_flag & P_PROFIL) { 439113874Sjhb if (p->p_profthreads != 0) { 440113874Sjhb p->p_flag |= P_STOPPROF; 441113874Sjhb while (p->p_profthreads != 0) 442113874Sjhb msleep(&p->p_profthreads, &p->p_mtx, PPAUSE, 443123740Speter "stopprof", 0); 444113874Sjhb p->p_flag &= ~P_STOPPROF; 445110530Sjulian } 446128852Scperciva if ((p->p_flag & P_PROFIL) == 0) 447128852Scperciva return; 448113874Sjhb p->p_flag &= ~P_PROFIL; 449169803Sjeff mtx_lock_spin(&time_lock); 450110296Sjake if (--profprocs == 0) 451110296Sjake cpu_stopprofclock(); 452169803Sjeff mtx_unlock_spin(&time_lock); 4531541Srgrimes } 4541541Srgrimes} 4551541Srgrimes 4561541Srgrimes/* 457170174Sjeff * Statistics clock. Updates rusage information and calls the scheduler 458170174Sjeff * to adjust priorities of the active thread. 459170174Sjeff * 460110296Sjake * This should be called by all active processors. 4611541Srgrimes */ 4621541Srgrimesvoid 463153666Sjhbstatclock(int usermode) 4641541Srgrimes{ 46517342Sbde struct rusage *ru; 46617342Sbde struct vmspace *vm; 467110296Sjake struct thread *td; 468110296Sjake struct proc *p; 469110296Sjake long rss; 470174070Speter long *cp_time; 4711541Srgrimes 472110296Sjake td = curthread; 473110296Sjake p = td->td_proc; 474110296Sjake 475174070Speter cp_time = (long *)PCPU_PTR(cp_time); 476153666Sjhb if (usermode) { 47753751Sbde /* 47853751Sbde * Charge the time as appropriate. 4791541Srgrimes */ 480163709Sjb#ifdef KSE 481116361Sdavidxu if (p->p_flag & P_SA) 482111028Sjeff thread_statclock(1); 483163709Sjb#endif 484155534Sphk td->td_uticks++; 485130551Sjulian if (p->p_nice > NZERO) 486174070Speter cp_time[CP_NICE]++; 4871541Srgrimes else 488174070Speter cp_time[CP_USER]++; 4891541Srgrimes } else { 4901541Srgrimes /* 4911541Srgrimes * Came from kernel mode, so we were: 4921541Srgrimes * - handling an interrupt, 4931541Srgrimes * - doing syscall or trap work on behalf of the current 4941541Srgrimes * user process, or 4951541Srgrimes * - spinning in the idle loop. 4961541Srgrimes * Whichever it is, charge the time as appropriate. 4971541Srgrimes * Note that we charge interrupts to the current process, 4981541Srgrimes * regardless of whether they are ``for'' that process, 4991541Srgrimes * so that we know how much of its real time was spent 5001541Srgrimes * in ``non-process'' (i.e., interrupt) work. 5011541Srgrimes */ 502151658Sjhb if ((td->td_pflags & TDP_ITHREAD) || 503151658Sjhb td->td_intr_nesting_level >= 2) { 504155534Sphk td->td_iticks++; 505174070Speter cp_time[CP_INTR]++; 50665557Sjasone } else { 507163709Sjb#ifdef KSE 508116361Sdavidxu if (p->p_flag & P_SA) 509111028Sjeff thread_statclock(0); 510163709Sjb#endif 511155455Sphk td->td_pticks++; 512155534Sphk td->td_sticks++; 513167327Sjulian if (!TD_IS_IDLETHREAD(td)) 514174070Speter cp_time[CP_SYS]++; 51565557Sjasone else 516174070Speter cp_time[CP_IDLE]++; 51765557Sjasone } 5181541Srgrimes } 5191541Srgrimes 52065782Sjhb /* Update resource usage integrals and maximums. */ 521131436Sjhb MPASS(p->p_vmspace != NULL); 522131436Sjhb vm = p->p_vmspace; 523170174Sjeff ru = &td->td_ru; 524131436Sjhb ru->ru_ixrss += pgtok(vm->vm_tsize); 525131436Sjhb ru->ru_idrss += pgtok(vm->vm_dsize); 526131436Sjhb ru->ru_isrss += pgtok(vm->vm_ssize); 527131436Sjhb rss = pgtok(vmspace_resident_count(vm)); 528131436Sjhb if (ru->ru_maxrss < rss) 529131436Sjhb ru->ru_maxrss = rss; 530170297Sjeff CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d", 531173600Sjulian td, td->td_name, td->td_priority, (stathz)?stathz:hz); 532174070Speter thread_lock_flags(td, MTX_QUIET); 533170297Sjeff sched_clock(td); 534170297Sjeff thread_unlock(td); 53576078Sjhb} 53666716Sjhb 53776078Sjhbvoid 538153666Sjhbprofclock(int usermode, uintfptr_t pc) 53976078Sjhb{ 540110296Sjake struct thread *td; 541110296Sjake#ifdef GPROF 542110296Sjake struct gmonparam *g; 543153490Sjhb uintfptr_t i; 544110296Sjake#endif 54576078Sjhb 546111032Sjulian td = curthread; 547153666Sjhb if (usermode) { 548110296Sjake /* 549110296Sjake * Came from user mode; CPU was in user state. 550110296Sjake * If this process is being profiled, record the tick. 551110530Sjulian * if there is no related user location yet, don't 552110530Sjulian * bother trying to count it. 553110296Sjake */ 554113874Sjhb if (td->td_proc->p_flag & P_PROFIL) 555153666Sjhb addupc_intr(td, pc, 1); 556110296Sjake } 557110296Sjake#ifdef GPROF 558110296Sjake else { 559110296Sjake /* 560110296Sjake * Kernel statistics are just like addupc_intr, only easier. 561110296Sjake */ 562110296Sjake g = &_gmonparam; 563153666Sjhb if (g->state == GMON_PROF_ON && pc >= g->lowpc) { 564153666Sjhb i = PC_TO_I(g, pc); 565110296Sjake if (i < g->textsize) { 566153666Sjhb KCOUNT(g, i)++; 567110296Sjake } 568110296Sjake } 569110296Sjake } 570110296Sjake#endif 5711541Srgrimes} 5721541Srgrimes 5731541Srgrimes/* 5741541Srgrimes * Return information about system clocks. 5751541Srgrimes */ 57612152Sphkstatic int 57762573Sphksysctl_kern_clockrate(SYSCTL_HANDLER_ARGS) 5781541Srgrimes{ 5791541Srgrimes struct clockinfo clkinfo; 5801541Srgrimes /* 5811541Srgrimes * Construct clockinfo structure. 5821541Srgrimes */ 58396052Sbde bzero(&clkinfo, sizeof(clkinfo)); 5841541Srgrimes clkinfo.hz = hz; 5851541Srgrimes clkinfo.tick = tick; 5861541Srgrimes clkinfo.profhz = profhz; 5871541Srgrimes clkinfo.stathz = stathz ? stathz : hz; 58812243Sphk return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req)); 5891541Srgrimes} 5902858Swollman 59112623SphkSYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD, 59288019Sluigi 0, 0, sysctl_kern_clockrate, "S,clockinfo", 59388019Sluigi "Rate and period of various kernel clocks"); 594116874Ssmkelly 595126383Sphk#ifdef SW_WATCHDOG 596126383Sphk 597126383Sphkstatic void 598165260Sn_hibmawatchdog_config(void *unused __unused, u_int cmd, int *error) 599116874Ssmkelly{ 600126383Sphk u_int u; 601116874Ssmkelly 602126386Sphk u = cmd & WD_INTERVAL; 603165260Sn_hibma if (u >= WD_TO_1SEC) { 604126383Sphk watchdog_ticks = (1 << (u - WD_TO_1SEC)) * hz; 605126383Sphk watchdog_enabled = 1; 606165260Sn_hibma *error = 0; 607126383Sphk } else { 608126383Sphk watchdog_enabled = 0; 609126383Sphk } 610116874Ssmkelly} 611116874Ssmkelly 612116874Ssmkelly/* 613116874Ssmkelly * Handle a watchdog timeout by dumping interrupt information and 614170075Semaste * then either dropping to DDB or panicking. 615116874Ssmkelly */ 616116874Ssmkellystatic void 617116874Ssmkellywatchdog_fire(void) 618116874Ssmkelly{ 619116874Ssmkelly int nintr; 620116874Ssmkelly u_int64_t inttotal; 621116874Ssmkelly u_long *curintr; 622116874Ssmkelly char *curname; 623116874Ssmkelly 624116874Ssmkelly curintr = intrcnt; 625116874Ssmkelly curname = intrnames; 626116874Ssmkelly inttotal = 0; 627116874Ssmkelly nintr = eintrcnt - intrcnt; 628157822Sjhb 629116874Ssmkelly printf("interrupt total\n"); 630116874Ssmkelly while (--nintr >= 0) { 631116874Ssmkelly if (*curintr) 632116874Ssmkelly printf("%-12s %20lu\n", curname, *curintr); 633116874Ssmkelly curname += strlen(curname) + 1; 634116874Ssmkelly inttotal += *curintr++; 635116874Ssmkelly } 636116908Ssmkelly printf("Total %20ju\n", (uintmax_t)inttotal); 637170075Semaste 638170075Semaste#if defined(KDB) && !defined(KDB_UNATTENDED) 639170075Semaste kdb_backtrace(); 640174898Srwatson kdb_enter(KDB_WHY_WATCHDOG, "watchdog timeout"); 641170075Semaste#else 642116874Ssmkelly panic("watchdog timeout"); 643170075Semaste#endif 644116874Ssmkelly} 645116874Ssmkelly 646126383Sphk#endif /* SW_WATCHDOG */ 647