From a97b795cfb1af4938cfe2aa077960cf7c6511550 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 22 Nov 2016 10:15:51 +1100 Subject: [PATCH 12/16] Make hrtimer granularity and minimum hrtimeout configurable in sysctl. --- kernel/sysctl.c | 22 ++++++++++++++++- kernel/time/clockevents.c | 8 ++---- kernel/time/hrtimer.c | 51 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c5ab6af20cd7..a16902f32e6a 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -135,7 +135,9 @@ extern int sched_interactive; extern int sched_iso_cpu; extern int sched_yield_type; #endif -#ifdef CONFIG_PRINTK +extern int hrtimer_granularity_us; +extern int hrtimeout_min_us; +#if defined(CONFIG_PRINTK) || defined(CONFIG_SCHED_MUQSS) static int ten_thousand = 10000; #endif #ifdef CONFIG_PERF_EVENTS @@ -1078,6 +1080,24 @@ static struct ctl_table kern_table[] = { .extra2 = &two, }, #endif + { + .procname = "hrtimer_granularity_us", + .data = &hrtimer_granularity_us, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .extra1 = &one, + .extra2 = &ten_thousand, + }, + { + .procname = "hrtimeout_min_us", + .data = &hrtimeout_min_us, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .extra1 = &one, + .extra2 = &ten_thousand, + }, #if defined(CONFIG_S390) && defined(CONFIG_SMP) { .procname = "spin_retry", diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 01d206062aa5..faf30b861235 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -198,13 +198,9 @@ int clockevents_tick_resume(struct clock_event_device *dev) #ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST -#ifdef CONFIG_SCHED_MUQSS +int __read_mostly hrtimer_granularity_us = 100; /* Limit min_delta to 100us */ -#define MIN_DELTA_LIMIT (NSEC_PER_SEC / 10000) -#else -/* Limit min_delta to a jiffie */ -#define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ) -#endif +#define MIN_DELTA_LIMIT (hrtimer_granularity_us * NSEC_PER_USEC) /** * clockevents_increase_min_delta - raise minimum delta of a clock event device diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index a4d3c44b8849..0f7f27adf16b 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -2034,7 +2034,7 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout); long __sched schedule_msec_hrtimeout(long timeout) { struct hrtimer_sleeper t; - int delta, secs, jiffs; + int delta, jiffs; ktime_t expires; if (!timeout) { @@ -2051,9 +2051,8 @@ long __sched schedule_msec_hrtimeout(long timeout) if (jiffs > 4 || hrtimer_resolution >= NSEC_PER_SEC / HZ || pm_freezing) return schedule_timeout(jiffs); - secs = timeout / 1000; delta = (timeout % 1000) * NSEC_PER_MSEC; - expires = ktime_set(secs, delta); + expires = ktime_set(0, delta); hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_set_expires_range_ns(&t.timer, expires, delta); @@ -2077,9 +2076,53 @@ long __sched schedule_msec_hrtimeout(long timeout) EXPORT_SYMBOL(schedule_msec_hrtimeout); +#define USECS_PER_SEC 1000000 +extern int hrtimer_granularity_us; + +static inline long schedule_usec_hrtimeout(long timeout) +{ + struct hrtimer_sleeper t; + ktime_t expires; + int delta; + + if (!timeout) { + __set_current_state(TASK_RUNNING); + return 0; + } + + if (hrtimer_resolution >= NSEC_PER_SEC / HZ) + return schedule_timeout(usecs_to_jiffies(timeout)); + + if (timeout < hrtimer_granularity_us) + timeout = hrtimer_granularity_us; + delta = (timeout % USECS_PER_SEC) * NSEC_PER_USEC; + expires = ktime_set(0, delta); + + hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_set_expires_range_ns(&t.timer, expires, delta); + + hrtimer_init_sleeper(&t, current); + + hrtimer_start_expires(&t.timer, HRTIMER_MODE_REL); + + if (likely(t.task)) + schedule(); + + hrtimer_cancel(&t.timer); + destroy_hrtimer_on_stack(&t.timer); + + __set_current_state(TASK_RUNNING); + + expires = hrtimer_expires_remaining(&t.timer); + timeout = ktime_to_us(expires); + return timeout < 0 ? 0 : timeout; +} + +int __read_mostly hrtimeout_min_us = 1000; + long __sched schedule_min_hrtimeout(void) { - return schedule_msec_hrtimeout(1); + return usecs_to_jiffies(schedule_usec_hrtimeout(hrtimeout_min_us)); } EXPORT_SYMBOL(schedule_min_hrtimeout); -- 2.17.1