27 #include <sys/cdefs.h>
34 #include "opt_device_polling.h"
35 #include "opt_kdtrace.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
43 #include <sys/mutex.h>
45 #include <sys/kernel.h>
46 #include <sys/sched.h>
48 #include <sys/sysctl.h>
49 #include <sys/timeet.h>
50 #include <sys/timetc.h>
52 #include <machine/atomic.h>
53 #include <machine/clock.h>
54 #include <machine/cpu.h>
55 #include <machine/smp.h>
58 #include <sys/dtrace_bsd.h>
59 cyclic_clock_func_t cyclic_clock_func = NULL;
70 static int round_freq(
struct eventtimer *et,
int freq);
76 static void cpu_new_callout(
int cpu,
int ticks);
81 #define ET_HW_LOCK(state) \
83 if (timer->et_flags & ET_FLAGS_PERCPU) \
84 mtx_lock_spin(&(state)->et_hw_mtx); \
86 mtx_lock_spin(&et_hw_mtx); \
89 #define ET_HW_UNLOCK(state) \
91 if (timer->et_flags & ET_FLAGS_PERCPU) \
92 mtx_unlock_spin(&(state)->et_hw_mtx); \
94 mtx_unlock_spin(&et_hw_mtx); \
97 static struct eventtimer *
timer = NULL;
111 TUNABLE_INT(
"kern.eventtimer.singlemul", &singlemul);
112 SYSCTL_INT(_kern_eventtimer, OID_AUTO, singlemul, CTLFLAG_RW, &singlemul,
113 0,
"Multiplier for periodic mode");
116 TUNABLE_INT(
"kern.eventtimer.idletick", &idletick);
117 SYSCTL_UINT(_kern_eventtimer, OID_AUTO, idletick, CTLFLAG_RW, &idletick,
118 0,
"Run periodic events when idle");
121 TUNABLE_INT(
"kern.eventtimer.activetick", &activetick);
122 SYSCTL_UINT(_kern_eventtimer, OID_AUTO, activetick, CTLFLAG_RW, &activetick,
123 0,
"Run all periodic events when active");
127 TUNABLE_INT(
"kern.eventtimer.periodic", &want_periodic);
148 #define FREQ2BT(freq, bt) \
151 (bt)->frac = ((uint64_t)0x8000000000000000 / (freq)) << 1; \
153 #define BT2FREQ(bt) \
154 (((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) / \
168 return (FILTER_HANDLED);
169 state = DPCPU_PTR(timerstate);
171 CTR4(KTR_SPARE2,
"ipi at %d: now %d.%08x%08x",
172 curcpu, now.sec, (
unsigned int)(now.frac >> 32),
173 (
unsigned int)(now.frac & 0xffffffff));
175 return (done ? FILTER_HANDLED : FILTER_STRAY);
185 struct trapframe *frame;
191 CTR4(KTR_SPARE2,
"handle at %d: now %d.%08x%08x",
192 curcpu, now->sec, (
unsigned int)(now->frac >> 32),
193 (
unsigned int)(now->frac & 0xffffffff));
200 frame = curthread->td_intr_frame;
201 usermode = TRAPF_USERMODE(frame);
202 pc = TRAPF_PC(frame);
205 state = DPCPU_PTR(timerstate);
208 while (bintime_cmp(now, &state->
nexthard, >=)) {
212 if ((
timer->et_flags & ET_FLAGS_PERCPU) == 0 &&
215 if (runs && fake < 2) {
220 while (bintime_cmp(now, &state->
nextstat, >=)) {
224 if (runs && fake < 2) {
230 while (bintime_cmp(now, &state->
nextprof, >=)) {
242 if (fake == 0 && cyclic_clock_func != NULL &&
243 state->nextcyc.sec != -1 &&
244 bintime_cmp(now, &state->nextcyc, >=)) {
245 state->nextcyc.sec = -1;
246 (*cyclic_clock_func)(frame);
275 state = DPCPU_PTR(timerstate);
278 if (idle || (!activetick && !
profiling &&
279 (
timer->et_flags & ET_FLAGS_PERCPU) == 0)) {
280 skip = idle ? 4 : (
stathz / 2);
284 CTR2(KTR_SPARE2,
"skip at %d: %d", curcpu, skip);
286 bintime_mul(&tmp, skip);
287 bintime_add(event, &tmp);
290 if (bintime_cmp(event, &state->
nextstat, >))
296 if (state->nextcyc.sec != -1 && bintime_cmp(event, &state->nextcyc, >))
297 *
event = state->nextcyc;
313 state = DPCPU_PTR(timerstate);
316 nonidle = !state->
idle;
317 if ((
timer->et_flags & ET_FLAGS_PERCPU) == 0) {
322 state = DPCPU_ID_PTR(cpu, timerstate);
323 nonidle += !state->
idle;
324 if (bintime_cmp(event, &state->
nextevent, >)) {
330 if (nonidle != 0 && bintime_cmp(event, &
nexthard, >))
333 CTR5(KTR_SPARE2,
"next at %d: next %d.%08x%08x by %d",
334 curcpu, event->sec, (
unsigned int)(event->frac >> 32),
335 (
unsigned int)(event->frac & 0xffffffff), c);
353 state = DPCPU_PTR(timerstate);
354 if (et->et_flags & ET_FLAGS_PERCPU) {
366 CTR4(KTR_SPARE2,
"intr at %d: now %d.%08x%08x",
367 curcpu, now.sec, (
unsigned int)(now.frac >> 32),
368 (
unsigned int)(now.frac & 0xffffffff));
373 if ((et->et_flags & ET_FLAGS_PERCPU) == 0 &&
smp_started) {
375 state = DPCPU_ID_PTR(cpu, timerstate);
378 if (bintime_cmp(&now, &state->
nextevent, >=)) {
399 state = DPCPU_ID_PTR(cpu, timerstate);
402 ipi_cpu(cpu, IPI_HARDCLOCK);
421 if (
timer->et_flags & ET_FLAGS_PERCPU) {
422 state = DPCPU_PTR(timerstate);
432 tmp = ((uint64_t)now->sec << 36) + (now->frac >> 28);
438 CTR5(KTR_SPARE2,
"load p at %d: now %d.%08x first in %d.%08x",
439 curcpu, now->sec, (
unsigned int)(now->frac >> 32),
440 new.sec, (
unsigned int)(
new.frac >> 32));
442 bintime_add(next, now);
447 eq = bintime_cmp(&
new, next, ==);
448 CTR5(KTR_SPARE2,
"load at %d: next %d.%08x%08x eq %d",
449 curcpu,
new.sec, (
unsigned int)(
new.frac >> 32),
450 (
unsigned int)(
new.frac & 0xffffffff),
454 bintime_sub(&
new, now);
468 if (periodic && (
timer->et_flags & ET_FLAGS_PERIODIC) == 0)
470 else if (!periodic && (
timer->et_flags & ET_FLAGS_ONESHOT) == 0)
472 singlemul = MIN(MAX(singlemul, 1), 20);
489 state = DPCPU_PTR(timerstate);
490 switch (atomic_load_acq_int(&state->
action)) {
497 atomic_store_rel_int(&state->
action, 0);
504 atomic_store_rel_int(&state->
action, 0);
507 if (atomic_readandclear_int(&state->
handle) && !
busy) {
541 state = DPCPU_ID_PTR(cpu, timerstate);
570 state = DPCPU_ID_PTR(cpu, timerstate);
571 atomic_store_rel_int(&state->
action,
572 (cpu == curcpu) ? 0 : ( start ? 1 : 2));
575 ipi_all_but_self(IPI_HARDCLOCK);
582 state = DPCPU_ID_PTR(cpu, timerstate);
583 if (atomic_load_acq_int(&state->
action))
598 if (et->et_frequency != 0) {
599 div = lmax((et->et_frequency + freq / 2) / freq, 1);
600 if (et->et_flags & ET_FLAGS_POW2DIV)
601 div = 1 << (flsl(div + div / 2) - 1);
602 freq = (et->et_frequency + div / 2) / div;
604 if (et->et_min_period.sec > 0)
606 else if (et->et_min_period.frac != 0)
607 freq = min(freq,
BT2FREQ(&et->et_min_period));
608 if (et->et_max_period.sec == 0 && et->et_max_period.frac != 0)
609 freq = max(freq,
BT2FREQ(&et->et_max_period));
624 state = DPCPU_ID_PTR(cpu, timerstate);
627 state->nextcyc.sec = -1;
637 if (
timer == NULL && periodic) {
639 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC);
643 ET_FLAGS_ONESHOT, ET_FLAGS_ONESHOT);
645 if (
timer == NULL && !periodic) {
647 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC);
650 panic(
"No usable event timer found!");
654 if (periodic && (
timer->et_flags & ET_FLAGS_PERIODIC) == 0)
656 else if (!periodic && (
timer->et_flags & ET_FLAGS_ONESHOT) == 0)
658 if (
timer->et_flags & ET_FLAGS_C3STOP)
666 if (singlemul <= 0 || singlemul > 20) {
667 if (
hz >= 1500 || (
hz % 128) == 0)
676 singlemul = max((base +
hz / 2) /
hz, 1);
677 hz = (base + singlemul / 2) / singlemul;
682 if (div >= singlemul && (div % singlemul) == 0)
713 state = DPCPU_PTR(timerstate);
716 if ((
timer->et_flags & ET_FLAGS_PERCPU) == 0 && periodic) {
723 if (
timer->et_flags & ET_FLAGS_PERCPU)
777 if (idletick ||
busy ||
778 (periodic && (
timer->et_flags & ET_FLAGS_PERCPU))
779 #ifdef DEVICE_POLLING
780 || curcpu == CPU_FIRST()
784 state = DPCPU_PTR(timerstate);
789 CTR4(KTR_SPARE2,
"idle at %d: now %d.%08x%08x",
790 curcpu, now.sec, (
unsigned int)(now.frac >> 32),
791 (
unsigned int)(now.frac & 0xffffffff));
811 state = DPCPU_PTR(timerstate);
818 CTR4(KTR_SPARE2,
"active at %d: now %d.%08x%08x",
819 curcpu, now.sec, (
unsigned int)(now.frac >> 32),
820 (
unsigned int)(now.frac & 0xffffffff));
823 td->td_intr_nesting_level++;
825 td->td_intr_nesting_level--;
831 clocksource_cyc_set(
const struct bintime *t)
836 state = DPCPU_PTR(timerstate);
842 CTR4(KTR_SPARE2,
"set_cyc at %d: now %d.%08x%08x",
843 curcpu,
now.sec, (
unsigned int)(
now.frac >> 32),
844 (
unsigned int)(
now.frac & 0xffffffff));
845 CTR4(KTR_SPARE2,
"set_cyc at %d: t %d.%08x%08x",
846 curcpu, t->sec, (
unsigned int)(t->frac >> 32),
847 (
unsigned int)(t->frac & 0xffffffff));
850 if (bintime_cmp(t, &state->nextcyc, ==)) {
855 if (bintime_cmp(&state->nextcyc, &state->
nextevent, >=)) {
868 cpu_new_callout(
int cpu,
int ticks)
873 CTR3(KTR_SPARE2,
"new co at %d: on %d in %d",
875 state = DPCPU_ID_PTR(cpu, timerstate);
885 if (periodic || (
timer->et_flags & ET_FLAGS_PERCPU) == 0) {
887 bintime_mul(&tmp, ticks - 1);
888 bintime_add(&tmp, &state->
nexthard);
889 if (bintime_cmp(&tmp, &state->
nextevent, <))
903 if (
timer->et_flags & ET_FLAGS_PERCPU) {
905 ipi_cpu(cpu, IPI_HARDCLOCK);
907 if (!cpu_idle_wakeup(cpu))
908 ipi_cpu(cpu, IPI_AST);
920 struct eventtimer *et;
925 snprintf(buf,
sizeof(buf),
"%s", et->et_name);
930 if (error != 0 || req->newptr == NULL ||
931 strcasecmp(buf, et->et_name) == 0) {
942 if (et->et_flags & ET_FLAGS_C3STOP)
944 if (
timer->et_flags & ET_FLAGS_C3STOP)
954 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
967 if (error != 0 || req->newptr == NULL)
971 periodic = want_periodic = val;
977 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
static int round_freq(struct eventtimer *et, int freq)
int et_stop(struct eventtimer *et)
static struct bintime hardperiod
static struct bintime statperiod
TUNABLE_INT("kern.eventtimer.singlemul",&singlemul)
int snprintf(char *str, size_t size, const char *format,...)
static void loadtimer(struct bintime *now, int first)
static char timername[32]
static int doconfigtimer(void)
struct eventtimer * et_find(const char *name, int check, int want)
void panic(const char *fmt,...)
void hardclock_cnt(int cnt, int usermode)
TUNABLE_STR("kern.eventtimer.timer", timername, sizeof(timername))
SYSCTL_INT(_kern_eventtimer, OID_AUTO, singlemul, CTLFLAG_RW,&singlemul, 0,"Multiplier for periodic mode")
SYSCTL_UINT(_kern_eventtimer, OID_AUTO, idletick, CTLFLAG_RW,&idletick, 0,"Run periodic events when idle")
static struct bintime profperiod
int sysctl_handle_string(SYSCTL_HANDLER_ARGS)
int callout_tickstofirst(int limit)
#define FREQ2BT(freq, bt)
static void getnextevent(struct bintime *event)
#define ET_HW_LOCK(state)
static DPCPU_DEFINE(struct pcpu_state, timerstate)
void(* callout_new_inserted)(int cpu, int ticks)
#define ET_HW_UNLOCK(state)
SYSCTL_PROC(_kern_eventtimer, OID_AUTO, timer, CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE, 0, 0, sysctl_kern_eventtimer_timer,"A","Chosen event timer")
static void timercb(struct eventtimer *et, void *arg)
static struct bintime nexttick
int et_init(struct eventtimer *et, et_event_cb_t *event, et_deregister_cb_t *deregister, void *arg)
static int handleevents(struct bintime *now, int fake)
int sysctl_handle_int(SYSCTL_HANDLER_ARGS)
static struct bintime timerperiod
static void setuptimer(void)
void statclock_cnt(int cnt, int usermode)
static int sysctl_kern_eventtimer_periodic(SYSCTL_HANDLER_ARGS)
void cpu_startprofclock(void)
void cpu_activeclock(void)
static struct eventtimer * timer
int et_start(struct eventtimer *et, struct bintime *first, struct bintime *period)
void cpu_stopprofclock(void)
static void configtimer(int start)
void bintime(struct bintime *bt)
void mtx_init(struct mtx *m, const char *name, const char *type, int opts)
static struct mtx et_hw_mtx
static int sysctl_kern_eventtimer_timer(SYSCTL_HANDLER_ARGS)
void profclock_cnt(int cnt, int usermode, uintfptr_t pc)
int et_free(struct eventtimer *et)
static struct bintime nexthard
void binuptime(struct bintime *bt)
void hardclock_sync(int cpu)
void cpu_initclocks_ap(void)
void cpu_initclocks_bsp(void)
static void getnextcpuevent(struct bintime *event, int idle)
void critical_enter(void)