Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_clock.c
Show First 20 Lines • Show All 329 Lines • ▼ Show 20 Lines | read_cpu_time(long *cp_time) | ||||
bzero(cp_time, sizeof(long) * CPUSTATES); | bzero(cp_time, sizeof(long) * CPUSTATES); | ||||
CPU_FOREACH(i) { | CPU_FOREACH(i) { | ||||
pc = pcpu_find(i); | pc = pcpu_find(i); | ||||
for (j = 0; j < CPUSTATES; j++) | for (j = 0; j < CPUSTATES; j++) | ||||
cp_time[j] += pc->pc_cp_time[j]; | cp_time[j] += pc->pc_cp_time[j]; | ||||
} | } | ||||
} | } | ||||
#ifdef SW_WATCHDOG | |||||
#include <sys/watchdog.h> | #include <sys/watchdog.h> | ||||
static int watchdog_ticks; | static int watchdog_ticks; | ||||
static int watchdog_enabled; | static int watchdog_enabled; | ||||
static void watchdog_fire(void); | static void watchdog_fire(void); | ||||
static void watchdog_config(void *, u_int, int *); | static void watchdog_config(void *, u_int, int *); | ||||
#endif /* SW_WATCHDOG */ | |||||
static void | |||||
watchdog_attach(void) | |||||
{ | |||||
EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0); | |||||
} | |||||
/* | /* | ||||
* Clock handling routines. | * Clock handling routines. | ||||
* | * | ||||
* This code is written to operate with two timers that run independently of | * This code is written to operate with two timers that run independently of | ||||
* each other. | * each other. | ||||
* | * | ||||
* The main timer, running hz times per second, is used to trigger interval | * The main timer, running hz times per second, is used to trigger interval | ||||
* timers, timeouts and rescheduling as needed. | * timers, timeouts and rescheduling as needed. | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | initclocks(void *dummy) | ||||
/* | /* | ||||
* Compute profhz/stathz, and fix profhz if needed. | * Compute profhz/stathz, and fix profhz if needed. | ||||
*/ | */ | ||||
i = stathz ? stathz : hz; | i = stathz ? stathz : hz; | ||||
if (profhz == 0) | if (profhz == 0) | ||||
profhz = i; | profhz = i; | ||||
psratio = profhz / i; | psratio = profhz / i; | ||||
#ifdef SW_WATCHDOG | #ifdef SW_WATCHDOG | ||||
EVENTHANDLER_REGISTER(watchdog_list, watchdog_config, NULL, 0); | /* Enable hardclock watchdog now, even if a hardware watchdog exists. */ | ||||
watchdog_attach(); | |||||
#else | |||||
/* Volunteer to run a software watchdog. */ | |||||
if (wdog_software_attach == NULL) | |||||
wdog_software_attach = watchdog_attach; | |||||
#endif | #endif | ||||
} | } | ||||
/* | /* | ||||
* Each time the real-time timer fires, this function is called on all CPUs. | * Each time the real-time timer fires, this function is called on all CPUs. | ||||
* Note that hardclock() calls hardclock_cpu() for the boot CPU, so only | * Note that hardclock() calls hardclock_cpu() for the boot CPU, so only | ||||
* the other CPUs in the system need to call this function. | * the other CPUs in the system need to call this function. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | hardclock(int usermode, uintfptr_t pc) | ||||
*/ | */ | ||||
if (stathz == 0) { | if (stathz == 0) { | ||||
profclock(usermode, pc); | profclock(usermode, pc); | ||||
statclock(usermode); | statclock(usermode); | ||||
} | } | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
hardclock_device_poll(); /* this is very short and quick */ | hardclock_device_poll(); /* this is very short and quick */ | ||||
#endif /* DEVICE_POLLING */ | #endif /* DEVICE_POLLING */ | ||||
#ifdef SW_WATCHDOG | |||||
if (watchdog_enabled > 0 && --watchdog_ticks <= 0) | if (watchdog_enabled > 0 && --watchdog_ticks <= 0) | ||||
watchdog_fire(); | watchdog_fire(); | ||||
#endif /* SW_WATCHDOG */ | |||||
} | } | ||||
void | void | ||||
hardclock_cnt(int cnt, int usermode) | hardclock_cnt(int cnt, int usermode) | ||||
{ | { | ||||
struct pstats *pstats; | struct pstats *pstats; | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
struct proc *p = td->td_proc; | struct proc *p = td->td_proc; | ||||
int *t = DPCPU_PTR(pcputicks); | int *t = DPCPU_PTR(pcputicks); | ||||
int flags, global, newticks; | int flags, global, newticks; | ||||
#ifdef SW_WATCHDOG | |||||
int i; | int i; | ||||
#endif /* SW_WATCHDOG */ | |||||
/* | /* | ||||
* Update per-CPU and possibly global ticks values. | * Update per-CPU and possibly global ticks values. | ||||
*/ | */ | ||||
*t += cnt; | *t += cnt; | ||||
do { | do { | ||||
global = ticks; | global = ticks; | ||||
newticks = *t - global; | newticks = *t - global; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
/* Dangerous and no need to call these things concurrently. */ | /* Dangerous and no need to call these things concurrently. */ | ||||
if (atomic_cmpset_acq_int(&devpoll_run, 0, 1)) { | if (atomic_cmpset_acq_int(&devpoll_run, 0, 1)) { | ||||
/* This is very short and quick. */ | /* This is very short and quick. */ | ||||
hardclock_device_poll(); | hardclock_device_poll(); | ||||
atomic_store_rel_int(&devpoll_run, 0); | atomic_store_rel_int(&devpoll_run, 0); | ||||
} | } | ||||
#endif /* DEVICE_POLLING */ | #endif /* DEVICE_POLLING */ | ||||
#ifdef SW_WATCHDOG | |||||
if (watchdog_enabled > 0) { | if (watchdog_enabled > 0) { | ||||
i = atomic_fetchadd_int(&watchdog_ticks, -newticks); | i = atomic_fetchadd_int(&watchdog_ticks, -newticks); | ||||
if (i > 0 && i <= newticks) | if (i > 0 && i <= newticks) | ||||
watchdog_fire(); | watchdog_fire(); | ||||
} | } | ||||
#endif /* SW_WATCHDOG */ | |||||
} | } | ||||
if (curcpu == CPU_FIRST()) | if (curcpu == CPU_FIRST()) | ||||
cpu_tick_calibration(); | cpu_tick_calibration(); | ||||
} | } | ||||
void | void | ||||
hardclock_sync(int cpu) | hardclock_sync(int cpu) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | sysctl_kern_clockrate(SYSCTL_HANDLER_ARGS) | ||||
return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req)); | return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req)); | ||||
} | } | ||||
SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, | SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, | ||||
CTLTYPE_STRUCT|CTLFLAG_RD|CTLFLAG_MPSAFE, | CTLTYPE_STRUCT|CTLFLAG_RD|CTLFLAG_MPSAFE, | ||||
0, 0, sysctl_kern_clockrate, "S,clockinfo", | 0, 0, sysctl_kern_clockrate, "S,clockinfo", | ||||
"Rate and period of various kernel clocks"); | "Rate and period of various kernel clocks"); | ||||
#ifdef SW_WATCHDOG | |||||
static void | static void | ||||
watchdog_config(void *unused __unused, u_int cmd, int *error) | watchdog_config(void *unused __unused, u_int cmd, int *error) | ||||
{ | { | ||||
u_int u; | u_int u; | ||||
u = cmd & WD_INTERVAL; | u = cmd & WD_INTERVAL; | ||||
if (u >= WD_TO_1SEC) { | if (u >= WD_TO_1SEC) { | ||||
watchdog_ticks = (1 << (u - WD_TO_1SEC)) * hz; | watchdog_ticks = (1 << (u - WD_TO_1SEC)) * hz; | ||||
Show All 32 Lines | |||||
#if defined(KDB) && !defined(KDB_UNATTENDED) | #if defined(KDB) && !defined(KDB_UNATTENDED) | ||||
kdb_backtrace(); | kdb_backtrace(); | ||||
kdb_enter(KDB_WHY_WATCHDOG, "watchdog timeout"); | kdb_enter(KDB_WHY_WATCHDOG, "watchdog timeout"); | ||||
#else | #else | ||||
panic("watchdog timeout"); | panic("watchdog timeout"); | ||||
#endif | #endif | ||||
} | } | ||||
#endif /* SW_WATCHDOG */ |