kern_clock.c revision 151747
197403Sobrien/*-
297403Sobrien * Copyright (c) 1982, 1986, 1991, 1993
3132720Skan *	The Regents of the University of California.  All rights reserved.
497403Sobrien * (c) UNIX System Laboratories, Inc.
597403Sobrien * All or some portions of this file are derived from material licensed
697403Sobrien * to the University of California by American Telephone and Telegraph
797403Sobrien * Co. or Unix System Laboratories, Inc. and are reproduced herein with
897403Sobrien * the permission of UNIX System Laboratories, Inc.
997403Sobrien *
1097403Sobrien * Redistribution and use in source and binary forms, with or without
1197403Sobrien * modification, are permitted provided that the following conditions
1297403Sobrien * are met:
1397403Sobrien * 1. Redistributions of source code must retain the above copyright
1497403Sobrien *    notice, this list of conditions and the following disclaimer.
1597403Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1697403Sobrien *    notice, this list of conditions and the following disclaimer in the
1797403Sobrien *    documentation and/or other materials provided with the distribution.
1897403Sobrien * 4. Neither the name of the University nor the names of its contributors
1997403Sobrien *    may be used to endorse or promote products derived from this software
2097403Sobrien *    without specific prior written permission.
2197403Sobrien *
2297403Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2397403Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2497403Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2597403Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2697403Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2797403Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2897403Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2997403Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3097403Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3197403Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32132720Skan * SUCH DAMAGE.
3397403Sobrien *
3497403Sobrien *	@(#)kern_clock.c	8.5 (Berkeley) 1/21/94
3597403Sobrien */
3697403Sobrien
3797403Sobrien#include <sys/cdefs.h>
3897403Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_clock.c 151747 2005-10-27 17:22:47Z emaste $");
3997403Sobrien
40132720Skan#include "opt_device_polling.h"
41132720Skan#include "opt_hwpmc_hooks.h"
4297403Sobrien#include "opt_ntp.h"
4397403Sobrien#include "opt_watchdog.h"
4497403Sobrien
4597403Sobrien#include <sys/param.h>
46117397Skan#include <sys/systm.h>
47117397Skan#include <sys/callout.h>
4897403Sobrien#include <sys/kdb.h>
4997403Sobrien#include <sys/kernel.h>
5097403Sobrien#include <sys/lock.h>
5197403Sobrien#include <sys/ktr.h>
5297403Sobrien#include <sys/mutex.h>
5397403Sobrien#include <sys/proc.h>
5497403Sobrien#include <sys/resource.h>
55132720Skan#include <sys/resourcevar.h>
5697403Sobrien#include <sys/sched.h>
57132720Skan#include <sys/signalvar.h>
5897403Sobrien#include <sys/smp.h>
5997403Sobrien#include <vm/vm.h>
6097403Sobrien#include <vm/pmap.h>
61132720Skan#include <vm/vm_map.h>
6297403Sobrien#include <sys/sysctl.h>
6397403Sobrien#include <sys/bus.h>
6497403Sobrien#include <sys/interrupt.h>
65132720Skan#include <sys/limits.h>
6697403Sobrien#include <sys/timetc.h>
6797403Sobrien
6897403Sobrien#include <machine/cpu.h>
69132720Skan
7097403Sobrien#ifdef GPROF
7197403Sobrien#include <sys/gmon.h>
7297403Sobrien#endif
73132720Skan
7497403Sobrien#ifdef HWPMC_HOOKS
7597403Sobrien#include <sys/pmckern.h>
7697403Sobrien#endif
77132720Skan
7897403Sobrien#ifdef DEVICE_POLLING
7997403Sobrienextern void hardclock_device_poll(void);
8097403Sobrien#endif /* DEVICE_POLLING */
81132720Skan
8297403Sobrienstatic void initclocks(void *dummy);
8397403SobrienSYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
8497403Sobrien
8597403Sobrien/* Some of these don't belong here, but it's easiest to concentrate them. */
86132720Skanlong cp_time[CPUSTATES];
8797403Sobrien
88132720Skanstatic int
8997403Sobriensysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
9097403Sobrien{
9197403Sobrien	int error;
92132720Skan#ifdef SCTL_MASK32
9397403Sobrien	int i;
9497403Sobrien	unsigned int cp_time32[CPUSTATES];
9597403Sobrien
96132720Skan	if (req->flags & SCTL_MASK32) {
9797403Sobrien		if (!req->oldptr)
9897403Sobrien			return SYSCTL_OUT(req, 0, sizeof(cp_time32));
9997403Sobrien		for (i = 0; i < CPUSTATES; i++)
100132720Skan			cp_time32[i] = (unsigned int)cp_time[i];
10197403Sobrien		error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32));
10297403Sobrien	} else
10397403Sobrien#endif
104132720Skan	{
10597403Sobrien		if (!req->oldptr)
10697403Sobrien			return SYSCTL_OUT(req, 0, sizeof(cp_time));
10797403Sobrien		error = SYSCTL_OUT(req, cp_time, sizeof(cp_time));
108132720Skan	}
10997403Sobrien	return error;
11097403Sobrien}
11197403Sobrien
112132720SkanSYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD,
11397403Sobrien    0,0, sysctl_kern_cp_time, "LU", "CPU time statistics");
11497403Sobrien
11597403Sobrien#ifdef SW_WATCHDOG
11697403Sobrien#include <sys/watchdog.h>
117132720Skan
11897403Sobrienstatic int watchdog_ticks;
119132720Skanstatic int watchdog_enabled;
12097403Sobrienstatic void watchdog_fire(void);
12197403Sobrienstatic void watchdog_config(void *, u_int, int *);
12297403Sobrien#endif /* SW_WATCHDOG */
123132720Skan
12497403Sobrien/*
12597403Sobrien * Clock handling routines.
12697403Sobrien *
127132720Skan * This code is written to operate with two timers that run independently of
12897403Sobrien * each other.
12997403Sobrien *
13097403Sobrien * The main timer, running hz times per second, is used to trigger interval
131132720Skan * timers, timeouts and rescheduling as needed.
13297403Sobrien *
13397403Sobrien * The second timer handles kernel and user profiling,
13497403Sobrien * and does resource use estimation.  If the second timer is programmable,
135132720Skan * it is randomized to avoid aliasing between the two clocks.  For example,
13697403Sobrien * the randomization prevents an adversary from always giving up the cpu
13797403Sobrien * just before its quantum expires.  Otherwise, it would never accumulate
13897403Sobrien * cpu ticks.  The mean frequency of the second timer is stathz.
139132720Skan *
14097403Sobrien * If no second timer exists, stathz will be zero; in this case we drive
14197403Sobrien * profiling and statistics off the main clock.  This WILL NOT be accurate;
14297403Sobrien * do not do it unless absolutely necessary.
143132720Skan *
14497403Sobrien * The statistics clock may (or may not) be run at a higher rate while
14597403Sobrien * profiling.  This profile clock runs at profhz.  We require that profhz
14697403Sobrien * be an integral multiple of stathz.
147132720Skan *
14897403Sobrien * If the statistics clock is running fast, it must be divided by the ratio
14997403Sobrien * profhz/stathz for statistics.  (For profiling, every tick counts.)
150117397Skan *
151117397Skan * Time-of-day is maintained using a "timecounter", which may or may
152117397Skan * not be related to the hardware generating the above mentioned
153117397Skan * interrupts.
154117397Skan */
155117397Skan
156117397Skanint	stathz;
157117397Skanint	profhz;
15897403Sobrienint	profprocs;
15997403Sobrienint	ticks;
16097403Sobrienint	psratio;
161132720Skan
16297403Sobrien/*
163117397Skan * Initialize clock frequencies and start both clocks running.
16497403Sobrien */
16597403Sobrien/* ARGSUSED*/
16697403Sobrienstatic void
167132720Skaninitclocks(dummy)
168132720Skan	void *dummy;
169132720Skan{
17097403Sobrien	register int i;
17197403Sobrien
17297403Sobrien	/*
17397403Sobrien	 * Set divisors to 1 (normal case) and let the machine-specific
174132720Skan	 * code do its bit.
17597403Sobrien	 */
17697403Sobrien	cpu_initclocks();
17797403Sobrien
17897403Sobrien	/*
179132720Skan	 * Compute profhz/stathz, and fix profhz if needed.
18097403Sobrien	 */
181132720Skan	i = stathz ? stathz : hz;
18297403Sobrien	if (profhz == 0)
18397403Sobrien		profhz = i;
18497403Sobrien	psratio = profhz / i;
185117397Skan#ifdef SW_WATCHDOG
186117397Skan	EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0);
187117397Skan#endif
188117397Skan}
189117397Skan
190117397Skan/*
191117397Skan * Each time the real-time timer fires, this function is called on all CPUs.
192117397Skan * Note that hardclock() calls hardclock_process() for the boot CPU, so only
193117397Skan * the other CPUs in the system need to call this function.
194117397Skan */
195117397Skanvoid
196117397Skanhardclock_process(frame)
197117397Skan	register struct clockframe *frame;
198117397Skan{
199117397Skan	struct pstats *pstats;
200117397Skan	struct thread *td = curthread;
201117397Skan	struct proc *p = td->td_proc;
202117397Skan
203117397Skan	/*
204117397Skan	 * Run current process's virtual and profile time, as needed.
205117397Skan	 */
206117397Skan	mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
207117397Skan	if (p->p_flag & P_SA) {
208117397Skan		/* XXXKSE What to do? */
209117397Skan	} else {
21097403Sobrien		pstats = p->p_stats;
211132720Skan		if (CLKF_USERMODE(frame) &&
212117397Skan		    timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) &&
21397403Sobrien		    itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) {
214132720Skan			p->p_sflag |= PS_ALRMPEND;
215117397Skan			td->td_flags |= TDF_ASTPENDING;
21697403Sobrien		}
217132720Skan		if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) &&
218117397Skan		    itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) {
21997403Sobrien			p->p_sflag |= PS_PROFPEND;
220132720Skan			td->td_flags |= TDF_ASTPENDING;
221117397Skan		}
22297403Sobrien	}
223132720Skan	mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
224117397Skan
225117397Skan#ifdef	HWPMC_HOOKS
226117397Skan	if (PMC_CPU_HAS_SAMPLES(PCPU_GET(cpuid)))
22797403Sobrien		PMC_CALL_HOOK_UNLOCKED(curthread, PMC_FN_DO_SAMPLES, NULL);
228132720Skan#endif
229117397Skan}
230117397Skan
23197403Sobrien/*
232132720Skan * The real-time timer, interrupting hz times per second.
233117397Skan */
23497403Sobrienvoid
235132720Skanhardclock(frame)
236117397Skan	register struct clockframe *frame;
237117397Skan{
23897403Sobrien	int need_softclock = 0;
239132720Skan
240117397Skan	CTR0(KTR_CLK, "hardclock fired");
24197403Sobrien	hardclock_process(frame);
242132720Skan
243117397Skan	tc_ticktock();
244117397Skan	/*
24597403Sobrien	 * If no separate statistics clock is available, run it from here.
246132720Skan	 *
247117397Skan	 * XXX: this only works for UP
248117397Skan	 */
24997403Sobrien	if (stathz == 0) {
250132720Skan		profclock(frame);
251117397Skan		statclock(frame);
25297403Sobrien	}
253132720Skan
254117397Skan#ifdef DEVICE_POLLING
25597403Sobrien	hardclock_device_poll();	/* this is very short and quick */
256132720Skan#endif /* DEVICE_POLLING */
257117397Skan
25897403Sobrien	/*
259132720Skan	 * Process callouts at a very low cpu priority, so we don't keep the
260117397Skan	 * relatively high clock interrupt priority any longer than necessary.
261117397Skan	 */
26297403Sobrien	mtx_lock_spin_flags(&callout_lock, MTX_QUIET);
263132720Skan	ticks++;
264117397Skan	if (TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL) {
26597403Sobrien		need_softclock = 1;
266132720Skan	} else if (softticks + 1 == ticks)
267117397Skan		++softticks;
26897403Sobrien	mtx_unlock_spin_flags(&callout_lock, MTX_QUIET);
269132720Skan
270117397Skan	/*
27197403Sobrien	 * swi_sched acquires sched_lock, so we don't want to call it with
27297403Sobrien	 * callout_lock held; incorrect locking order.
27397403Sobrien	 */
274117397Skan	if (need_softclock)
275117397Skan		swi_sched(softclock_ih, 0);
276117397Skan
277117397Skan#ifdef SW_WATCHDOG
278117397Skan	if (watchdog_enabled > 0 && --watchdog_ticks <= 0)
279117397Skan		watchdog_fire();
280117397Skan#endif /* SW_WATCHDOG */
281117397Skan}
282117397Skan
283117397Skan/*
284117397Skan * Compute number of ticks in the specified amount of time.
28597403Sobrien */
286132720Skanint
287117397Skantvtohz(tv)
288117397Skan	struct timeval *tv;
289132720Skan{
290132720Skan	register unsigned long ticks;
291117397Skan	register long sec, usec;
292132720Skan
293132720Skan	/*
294117397Skan	 * If the number of usecs in the whole seconds part of the time
295117397Skan	 * difference fits in a long, then the total number of usecs will
296117397Skan	 * fit in an unsigned long.  Compute the total and convert it to
297132720Skan	 * ticks, rounding up and adding 1 to allow for the current tick
298132720Skan	 * to expire.  Rounding also depends on unsigned long arithmetic
299117397Skan	 * to avoid overflow.
300132720Skan	 *
30197403Sobrien	 * Otherwise, if the number of ticks in the whole seconds part of
302117397Skan	 * the time difference fits in a long, then convert the parts to
303117397Skan	 * ticks separately and add, using similar rounding methods and
304117397Skan	 * overflow avoidance.  This method would work in the previous
305117397Skan	 * case but it is slightly slower and assumes that hz is integral.
306117397Skan	 *
307117397Skan	 * Otherwise, round the time difference down to the maximum
308117397Skan	 * representable value.
309117397Skan	 *
310117397Skan	 * If ints have 32 bits, then the maximum value for any timeout in
311117397Skan	 * 10ms ticks is 248 days.
312117397Skan	 */
313117397Skan	sec = tv->tv_sec;
314117397Skan	usec = tv->tv_usec;
315117397Skan	if (usec < 0) {
31697403Sobrien		sec--;
317132720Skan		usec += 1000000;
318117397Skan	}
319132720Skan	if (sec < 0) {
320132720Skan#ifdef DIAGNOSTIC
321117397Skan		if (usec > 0) {
322132720Skan			sec++;
323132720Skan			usec -= 1000000;
324117397Skan		}
325117397Skan		printf("tvotohz: negative time difference %ld sec %ld usec\n",
326117397Skan		       sec, usec);
327117397Skan#endif
328132720Skan		ticks = 1;
329132720Skan	} else if (sec <= LONG_MAX / 1000000)
330117397Skan		ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
331132720Skan			/ tick + 1;
332132720Skan	else if (sec <= LONG_MAX / hz)
333117397Skan		ticks = sec * hz
334132720Skan			+ ((unsigned long)usec + (tick - 1)) / tick + 1;
335132720Skan	else
336117397Skan		ticks = LONG_MAX;
337132720Skan	if (ticks > INT_MAX)
33897403Sobrien		ticks = INT_MAX;
339117397Skan	return ((int)ticks);
340117397Skan}
341117397Skan
342117397Skan/*
343117397Skan * Start profiling on a process.
344117397Skan *
345117397Skan * Kernel profiling passes proc0 which never exits and hence
346117397Skan * keeps the profile clock running constantly.
347117397Skan */
348117397Skanvoid
34997403Sobrienstartprofclock(p)
350132720Skan	register struct proc *p;
351117397Skan{
352132720Skan
353132720Skan	/*
354117397Skan	 * XXX; Right now sched_lock protects statclock(), but perhaps
355132720Skan	 * it should be protected later on by a time_lock, which would
356132720Skan	 * cover psdiv, etc. as well.
357117397Skan	 */
358132720Skan	PROC_LOCK_ASSERT(p, MA_OWNED);
35997403Sobrien	if (p->p_flag & P_STOPPROF)
360132720Skan		return;
361117397Skan	if ((p->p_flag & P_PROFIL) == 0) {
36297403Sobrien		mtx_lock_spin(&sched_lock);
36397403Sobrien		p->p_flag |= P_PROFIL;
36497403Sobrien		if (++profprocs == 1)
365132720Skan			cpu_startprofclock();
366107606Sobrien		mtx_unlock_spin(&sched_lock);
367107606Sobrien	}
36897403Sobrien}
36997403Sobrien
37097403Sobrien/*
371117397Skan * Stop profiling on a process.
372132720Skan */
373132720Skanvoid
374132720Skanstopprofclock(p)
375132720Skan	register struct proc *p;
376117397Skan{
37797403Sobrien
37897403Sobrien	PROC_LOCK_ASSERT(p, MA_OWNED);
37997403Sobrien	if (p->p_flag & P_PROFIL) {
38097403Sobrien		if (p->p_profthreads != 0) {
38197403Sobrien			p->p_flag |= P_STOPPROF;
38297403Sobrien			while (p->p_profthreads != 0)
38397403Sobrien				msleep(&p->p_profthreads, &p->p_mtx, PPAUSE,
384117397Skan				    "stopprof", 0);
385132720Skan			p->p_flag &= ~P_STOPPROF;
386132720Skan		}
387132720Skan		if ((p->p_flag & P_PROFIL) == 0)
388132720Skan			return;
389132720Skan		mtx_lock_spin(&sched_lock);
390132720Skan		p->p_flag &= ~P_PROFIL;
391132720Skan		if (--profprocs == 0)
392132720Skan			cpu_stopprofclock();
393117397Skan		mtx_unlock_spin(&sched_lock);
39497403Sobrien	}
39597403Sobrien}
396117397Skan
397132720Skan/*
398132720Skan * Statistics clock.  Grab profile sample, and if divider reaches 0,
399132720Skan * do process and kernel statistics.  Most of the statistics are only
400132720Skan * used by user-level statistics programs.  The main exceptions are
401132720Skan * ke->ke_uticks, p->p_rux.rux_sticks, p->p_rux.rux_iticks, and p->p_estcpu.
402132720Skan * This should be called by all active processors.
403132720Skan */
404132720Skanvoid
405117397Skanstatclock(frame)
406132720Skan	register struct clockframe *frame;
40797403Sobrien{
40897403Sobrien	struct rusage *ru;
40997403Sobrien	struct vmspace *vm;
410117397Skan	struct thread *td;
411117397Skan	struct proc *p;
412117397Skan	long rss;
413117397Skan
414117397Skan	td = curthread;
415117397Skan	p = td->td_proc;
416132720Skan
417132720Skan	mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
418132720Skan	if (CLKF_USERMODE(frame)) {
419132720Skan		/*
420132720Skan		 * Charge the time as appropriate.
421117397Skan		 */
42297403Sobrien		if (p->p_flag & P_SA)
42397403Sobrien			thread_statclock(1);
42497403Sobrien		p->p_rux.rux_uticks++;
42597403Sobrien		if (p->p_nice > NZERO)
42697403Sobrien			cp_time[CP_NICE]++;
42797403Sobrien		else
428132720Skan			cp_time[CP_USER]++;
429132720Skan	} else {
430132720Skan		/*
43197403Sobrien		 * Came from kernel mode, so we were:
432132720Skan		 * - handling an interrupt,
433132720Skan		 * - doing syscall or trap work on behalf of the current
43497403Sobrien		 *   user process, or
43597403Sobrien		 * - spinning in the idle loop.
43697403Sobrien		 * Whichever it is, charge the time as appropriate.
437132720Skan		 * Note that we charge interrupts to the current process,
438132720Skan		 * regardless of whether they are ``for'' that process,
439132720Skan		 * so that we know how much of its real time was spent
44097403Sobrien		 * in ``non-process'' (i.e., interrupt) work.
441132720Skan		 */
442132720Skan		if ((td->td_pflags & TDP_ITHREAD) ||
443132720Skan		    td->td_intr_nesting_level >= 2) {
44497403Sobrien			p->p_rux.rux_iticks++;
44597403Sobrien			cp_time[CP_INTR]++;
446132720Skan		} else {
44797403Sobrien			if (p->p_flag & P_SA)
448132720Skan				thread_statclock(0);
44997403Sobrien			td->td_sticks++;
45097403Sobrien			p->p_rux.rux_sticks++;
451132720Skan			if (td != PCPU_GET(idlethread))
45297403Sobrien				cp_time[CP_SYS]++;
45397403Sobrien			else
45497403Sobrien				cp_time[CP_IDLE]++;
455132720Skan		}
456132720Skan	}
457132720Skan	CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d",
458132720Skan	    td, td->td_proc->p_comm, td->td_priority, (stathz)?stathz:hz);
45997403Sobrien
46097403Sobrien	sched_clock(td);
46197403Sobrien
46297403Sobrien	/* Update resource usage integrals and maximums. */
463132720Skan	MPASS(p->p_stats != NULL);
46497403Sobrien	MPASS(p->p_vmspace != NULL);
46597403Sobrien	vm = p->p_vmspace;
466117397Skan	ru = &p->p_stats->p_ru;
467132720Skan	ru->ru_ixrss += pgtok(vm->vm_tsize);
468132720Skan	ru->ru_idrss += pgtok(vm->vm_dsize);
46997403Sobrien	ru->ru_isrss += pgtok(vm->vm_ssize);
47097403Sobrien	rss = pgtok(vmspace_resident_count(vm));
471132720Skan	if (ru->ru_maxrss < rss)
472132720Skan		ru->ru_maxrss = rss;
47397403Sobrien	mtx_unlock_spin_flags(&sched_lock, MTX_QUIET);
474132720Skan}
475132720Skan
476132720Skanvoid
47797403Sobrienprofclock(frame)
478132720Skan	register struct clockframe *frame;
47997403Sobrien{
480132720Skan	struct thread *td;
48197403Sobrien#ifdef GPROF
48297403Sobrien	struct gmonparam *g;
48397403Sobrien	int i;
48497403Sobrien#endif
48597403Sobrien
48697403Sobrien	td = curthread;
48797403Sobrien	if (CLKF_USERMODE(frame)) {
488132720Skan		/*
489132720Skan		 * Came from user mode; CPU was in user state.
49097403Sobrien		 * If this process is being profiled, record the tick.
49197403Sobrien		 * if there is no related user location yet, don't
49297403Sobrien		 * bother trying to count it.
49397403Sobrien		 */
49497403Sobrien		if (td->td_proc->p_flag & P_PROFIL)
49597403Sobrien			addupc_intr(td, CLKF_PC(frame), 1);
49697403Sobrien	}
497132720Skan#ifdef GPROF
498132720Skan	else {
49997403Sobrien		/*
50097403Sobrien		 * Kernel statistics are just like addupc_intr, only easier.
501117397Skan		 */
502117397Skan		g = &_gmonparam;
503117397Skan		if (g->state == GMON_PROF_ON) {
504117397Skan			i = CLKF_PC(frame) - g->lowpc;
505117397Skan			if (i < g->textsize) {
506132720Skan				i /= HISTFRACTION * sizeof(*g->kcount);
50797403Sobrien				g->kcount[i]++;
50897403Sobrien			}
509117397Skan		}
510117397Skan	}
511117397Skan#endif
512117397Skan}
513117397Skan
514117397Skan/*
515117397Skan * Return information about system clocks.
516132720Skan */
51797403Sobrienstatic int
518132720Skansysctl_kern_clockrate(SYSCTL_HANDLER_ARGS)
519132720Skan{
520132720Skan	struct clockinfo clkinfo;
521132720Skan	/*
52297403Sobrien	 * Construct clockinfo structure.
52397403Sobrien	 */
524117397Skan	bzero(&clkinfo, sizeof(clkinfo));
525117397Skan	clkinfo.hz = hz;
526117397Skan	clkinfo.tick = tick;
527117397Skan	clkinfo.profhz = profhz;
528117397Skan	clkinfo.stathz = stathz ? stathz : hz;
529117397Skan	return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req));
530117397Skan}
531117397Skan
532132720SkanSYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD,
53397403Sobrien	0, 0, sysctl_kern_clockrate, "S,clockinfo",
534132720Skan	"Rate and period of various kernel clocks");
535132720Skan
536132720Skan#ifdef SW_WATCHDOG
537132720Skan
53897403Sobrienstatic void
53997403Sobrienwatchdog_config(void *unused __unused, u_int cmd, int *err)
540117397Skan{
541117397Skan	u_int u;
542117397Skan
543117397Skan	u = cmd & WD_INTERVAL;
544117397Skan	if ((cmd & WD_ACTIVE) && u >= WD_TO_1SEC) {
545117397Skan		watchdog_ticks = (1 << (u - WD_TO_1SEC)) * hz;
546117397Skan		watchdog_enabled = 1;
547117397Skan		*err = 0;
548117397Skan	} else {
549132720Skan		watchdog_enabled = 0;
55097403Sobrien	}
55197403Sobrien}
55297403Sobrien
55397403Sobrien/*
55497403Sobrien * Handle a watchdog timeout by dumping interrupt information and
55597403Sobrien * then either dropping to DDB or panicing.
55697403Sobrien */
55797403Sobrienstatic void
558117397Skanwatchdog_fire(void)
559117397Skan{
560117397Skan	int nintr;
561117397Skan	u_int64_t inttotal;
562117397Skan	u_long *curintr;
563117397Skan	char *curname;
564132720Skan
56597403Sobrien	curintr = intrcnt;
56697403Sobrien	curname = intrnames;
567117397Skan	inttotal = 0;
568117397Skan	nintr = eintrcnt - intrcnt;
569117397Skan
570117397Skan	printf("interrupt                   total\n");
571117397Skan	while (--nintr >= 0) {
572117397Skan		if (*curintr)
573117397Skan			printf("%-12s %20lu\n", curname, *curintr);
574117397Skan		curname += strlen(curname) + 1;
575117397Skan		inttotal += *curintr++;
576132720Skan	}
57797403Sobrien	printf("Total        %20ju\n", (uintmax_t)inttotal);
57897403Sobrien
579117397Skan#ifdef KDB
580117397Skan	kdb_backtrace();
581117397Skan	kdb_enter("watchdog timeout");
582117397Skan#else
583117397Skan	panic("watchdog timeout");
584132720Skan#endif /* KDB */
58597403Sobrien}
586132720Skan
587132720Skan#endif /* SW_WATCHDOG */
588132720Skan