From 6dce94df14b747c6782104ed121040d1d08ee1bc Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 22 Nov 2016 10:15:51 +1100 Subject: [PATCH 11/16] Make hrtimer granularity and minimum hrtimeout configurable in sysctl. Set default granularity to 100us and min timeout to 500us. --- kernel/sysctl.c | 23 ++++++++++++++++-- kernel/time/clockevents.c | 8 ++----- kernel/time/hrtimer.c | 49 +++++++++++++++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c85a2efde05e..a36443da01a2 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -128,7 +128,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 @@ -1901,7 +1903,24 @@ static struct ctl_table kern_table[] = { }, #endif /* CONFIG_SMP && CONFIG_SCHEDSTATS */ #endif /* CONFIG_SCHED_MUQSS */ - + { + .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_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) { .procname = "sched_energy_aware", 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 0f24153c51a1..30d4e9713e2d 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -2226,7 +2226,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) { @@ -2243,9 +2243,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); @@ -2267,9 +2266,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