From faa3a88e08197367709a096e7f1cf94120e9d857 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 22 Nov 2016 10:15:51 +1100 Subject: [PATCH 11/19] Make hrtimer granularity and minimum hrtimeout configurable in sysctl. Set default granularity to 100us and min timeout to 500us. --- kernel/sysctl.c | 22 +++++++++++++++++- kernel/time/clockevents.c | 8 ++----- kernel/time/hrtimer.c | 49 +++++++++++++++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index d5a5459e5860..4c9cd46d850f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -140,7 +140,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 @@ -1109,6 +1111,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 7a61971cca74..544c58c29267 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -190,13 +190,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 04b876253ee5..ab38dde6e106 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -2219,7 +2219,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) { @@ -2236,9 +2236,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_sleeper_on_stack(&t, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_set_expires_range_ns(&t.timer, expires, delta); @@ -2260,9 +2259,51 @@ 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_sleeper_on_stack(&t, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_set_expires_range_ns(&t.timer, expires, delta); + + hrtimer_sleeper_start_expires(&t, 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 = 500; + 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.25.1