summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCon Kolivas <kernel@kolivas.org>2016-11-22 10:15:51 +1100
committerCon Kolivas <kernel@kolivas.org>2018-12-29 18:37:28 +1100
commita97b795cfb1af4938cfe2aa077960cf7c6511550 (patch)
tree439aa98d1c578d45ac10058cd88b8fd93ddcfd35
parenta9f187e58e0bde767cbcbdc7477712ee7ebbfe66 (diff)
Make hrtimer granularity and minimum hrtimeout configurable in sysctl.
-rw-r--r--kernel/sysctl.c22
-rw-r--r--kernel/time/clockevents.c8
-rw-r--r--kernel/time/hrtimer.c51
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);