hrtimers: add slop parameter
Subsystems (7)
RFC PATCH 1/1 hrtimers: add slop parameter
(I don't really like this patch yet, but wanted to get something out there)
After discussion with Thomas Gleixner, we came up with the idea of introducing a new parameter to hrtimers (and probably eventually all timers in the kernel, then onto userspace). I call it "slop", and it is an indication of how precise a timer should be.
The idea is that this "slop" can be used to calculate what timers can be batched, and maybe even eventually unify normal and high res timers. A timer should fire no earlier than its expiry, but we don't care if it's delayed until after expiry+slop.
For this patch, DEFAULT_SLOP (currently 0) is used everywhere, and the parameter is unused.
drivers/kvm/lapic.c +2 -1
@@ -968,7 +968,8 @@ int kvm_create_lapic(struct kvm_vcpu *vcmemset (apic->regs,0 ,PAGE_SIZE ); apic->vcpu = vcpu; -hrtimer_init (&apic->timer.dev,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS ); +hrtimer_init (&apic->timer.dev,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS , +DEFAULT_SLOP ); apic->timer.dev.function = apic_timer_fn; apic->base_address =APIC_DEFAULT_PHYS_BASE ; vcpu->apic_base =APIC_DEFAULT_PHYS_BASE ;
drivers/net/virtio_net.c +2 -1
@@ -403,7 +403,8 @@ static int virtnet_probe(struct virtio_dnetif_napi_add (dev, &vi->napi, virtnet_poll,16 ); vi->dev = dev; vi->vdev = vdev; -hrtimer_init (&vi->tx_timer,CLOCK_REALTIME ,HRTIMER_MODE_REL ); +hrtimer_init (&vi->tx_timer,CLOCK_REALTIME ,HRTIMER_MODE_REL , +DEFAULT_SLOP ); vi->tx_timer.function = kick_xmit; vi->tx_timer.cb_mode =HRTIMER_CB_SOFTIRQ ; vi->out_max =-1U ;
include/linux/hrtimer.h +4 -1
@@ -100,6 +100,7 @@ enum hrtimer_cb_mode {* @cb_mode: high resolution timer feature to select the callback execution * mode * @cb_entry: list head to enqueue an expired timer into the callback list +* @slop: how much extra delay can be added (eg. for deferring wakeups) * @start_site: timer statistics field to store the site where the timer * was started * @start_comm: timer statistics field to store the name of the process which
@@ -118,6 +119,7 @@ struct hrtimer {#ifdef CONFIG_HIGH_RES_TIMERS enum hrtimer_cb_mode cb_mode;struct list_head cb_entry; +ktime_t slop;#endif #ifdef CONFIG_TIMER_STATS void *start_site;
@@ -256,8 +258,9 @@ extern ktime_t ktime_get_real(void);/* Exported timer functions: */ /* Initialize timers: */ +#define DEFAULT_SLOP ((ktime_t) { .tv64 = 0 })extern void hrtimer_init (struct hrtimer *timer,clockid_t which_clock, -enum hrtimer_mode mode); +enum hrtimer_mode mode,ktime_t slop);/* Basic timer operations: */ extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
kernel/fork.c +2 -1
@@ -874,7 +874,8 @@ static int copy_signal(unsigned long cloinit_sigpending (&sig->shared_pending);INIT_LIST_HEAD (&sig->posix_timers); -hrtimer_init (&sig->real_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_REL ); +hrtimer_init (&sig->real_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_REL , +DEFAULT_SLOP ); sig->it_real_incr.tv64 =0 ; sig->real_timer.function = it_real_fn; sig->tsk = tsk;
kernel/futex.c +4 -2
@@ -1247,7 +1247,8 @@ static int futex_wait(u32 __user *uaddr,if (!abs_time)schedule ();else { -hrtimer_init (&t.timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS ); +hrtimer_init (&t.timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS , +DEFAULT_SLOP );hrtimer_init_sleeper (&t, current); t.timer.expires = *abs_time;
@@ -1344,7 +1345,8 @@ static int futex_lock_pi(u32 __user *uadif (time) { to = &timeout; -hrtimer_init (&to->timer,CLOCK_REALTIME ,HRTIMER_MODE_ABS ); +hrtimer_init (&to->timer,CLOCK_REALTIME ,HRTIMER_MODE_ABS , +DEFAULT_SLOP );hrtimer_init_sleeper (to, current); to->timer.expires = *time; }
kernel/hrtimer.c +10 -6
@@ -522,9 +522,10 @@ static inline void hrtimer_init_hres(str/* * Initialize the high resolution related parts of a hrtimer */ -static inline void hrtimer_init_timer_hres (struct hrtimer *timer) +static inline void hrtimer_init_timer_hres (struct hrtimer *timer,ktime_t slop) {INIT_LIST_HEAD (&timer->cb_entry); + timer->slop = slop; }/*
@@ -621,7 +622,9 @@ static inline int hrtimer_cb_pending(strstatic inline int hrtimer_cb_pending (struct hrtimer *timer) {return 0 ; }static inline void hrtimer_remove_cb_pending (struct hrtimer *timer) { }static inline void hrtimer_init_hres (struct hrtimer_cpu_base *base) { } -static inline void hrtimer_init_timer_hres (struct hrtimer *timer) { } +static inline void hrtimer_init_timer_hres (struct hrtimer *timer,ktime_t slop) +{ +}#endif /* CONFIG_HIGH_RES_TIMERS */
@@ -987,9 +990,10 @@ ktime_t hrtimer_get_next_event(void)* @timer: the timer to be initialized * @clock_id: the clock to be used * @mode: timer mode abs/rel +* @slop: delay which can be added to timer without significant effect. */ void hrtimer_init (struct hrtimer *timer,clockid_t clock_id, -enum hrtimer_mode mode) +enum hrtimer_mode mode,ktime_t slop) {struct hrtimer_cpu_base *cpu_base;
@@ -1001,7 +1005,7 @@ void hrtimer_init(struct hrtimer *timer, clock_id =CLOCK_MONOTONIC ; timer->base = &cpu_base->clock_base[clock_id]; -hrtimer_init_timer_hres (timer); +hrtimer_init_timer_hres (timer, slop);#ifdef CONFIG_TIMER_STATS timer->start_site =NULL ;
@@ -1299,7 +1303,7 @@ long __sched hrtimer_nanosleep_restart(s restart->fn = do_no_restart_syscall; -hrtimer_init (&t.timer, restart->arg0,HRTIMER_MODE_ABS ); +hrtimer_init (&t.timer, restart->arg0,HRTIMER_MODE_ABS ,DEFAULT_SLOP ); t.timer.expires.tv64 = ((u64 )restart->arg3 <<32 ) | (u64 ) restart->arg2;if (do_nanosleep (&t,HRTIMER_MODE_ABS ))
@@ -1326,7 +1330,7 @@ long hrtimer_nanosleep(struct timespec *struct hrtimer_sleeper t;ktime_t rem; -hrtimer_init (&t.timer, clockid, mode); +hrtimer_init (&t.timer, clockid, mode,DEFAULT_SLOP ); t.timer.expires =timespec_to_ktime (*rqtp);if (do_nanosleep (&t, mode))return 0 ;
kernel/posix-timers.c +3 -2
@@ -194,7 +194,8 @@ static inline int common_clock_set(conststatic int common_timer_create (struct k_itimer *new_timer) { -hrtimer_init (&new_timer->it.real.timer, new_timer->it_clock,0 ); +hrtimer_init (&new_timer->it.real.timer, new_timer->it_clock,0 , +DEFAULT_SLOP );return 0 ; }
@@ -755,7 +756,7 @@ common_timer_set(struct k_itimer *timr,return 0 ; mode = flags &TIMER_ABSTIME ?HRTIMER_MODE_ABS :HRTIMER_MODE_REL ; -hrtimer_init (&timr->it.real.timer, timr->it_clock, mode); +hrtimer_init (&timr->it.real.timer, timr->it_clock, mode,DEFAULT_SLOP ); timr->it.real.timer.function = posix_timer_fn; timer->expires =timespec_to_ktime (new_setting->it_value);
kernel/time/tick-sched.c +4 -2
@@ -475,7 +475,8 @@ static void tick_nohz_switch_to_nohz(voi* Recycle the hrtimer in ts, so we can share the * hrtimer_forward with the highres code. */ -hrtimer_init (&ts->sched_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS ); +hrtimer_init (&ts->sched_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS , +DEFAULT_SLOP );/* Get the next period */ next =tick_init_jiffy_update ();
@@ -579,7 +580,8 @@ void tick_setup_sched_timer(void)/* * Emulate tick processing via per-CPU hrtimers: */ -hrtimer_init (&ts->sched_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS ); +hrtimer_init (&ts->sched_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS , +DEFAULT_SLOP ); ts->sched_timer.function = tick_sched_timer; ts->sched_timer.cb_mode =HRTIMER_CB_IRQSAFE_NO_SOFTIRQ ;