Skip to content

Instantly share code, notes, and snippets.

@glitsj16
Created March 22, 2023 21:58
Show Gist options
  • Save glitsj16/46ba4eebbde9727577c2a2075dfda3c1 to your computer and use it in GitHub Desktop.
Save glitsj16/46ba4eebbde9727577c2a2075dfda3c1 to your computer and use it in GitHub Desktop.
From 308a45413e82f6be1bf10864f5f9eab6bf0dd799 Mon Sep 17 00:00:00 2001
From: graysky <therealgraysky@proton.me>
Date: Wed, 5 Oct 2022 05:45:01 -0400
Subject: [PATCH 8/8] clockevents, hrtimer: Make hrtimer granularity and
minimum hrtimeout configurable in sysctl. Set default granularity to 100us
and min timeout to 500us
---
kernel/sysctl.c | 21 +++++++++++++++++
kernel/time/clockevents.c | 3 ++-
kernel/time/hrtimer.c | 49 +++++++++++++++++++++++++++++++++++----
3 files changed, 68 insertions(+), 5 deletions(-)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c6d9dec11b74..1c806db94b22 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -92,6 +92,9 @@ EXPORT_SYMBOL_GPL(sysctl_long_vals);
#if defined(CONFIG_SYSCTL)
/* Constants used for minimum and maximum */
+static int ten_thousand = 10000;
+extern int hrtimer_granularity_us;
+extern int hrtimeout_min_us;
#ifdef CONFIG_PERF_EVENTS
static const int six_hundred_forty_kb = 640 * 1024;
@@ -1642,6 +1642,24 @@
static struct ctl_table kern_table[] = {
{
+ .procname = "hrtimer_granularity_us",
+ .data = &hrtimer_granularity_us,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = SYSCTL_ONE,
+ .extra2 = &ten_thousand,
+ },
+ {
+ .procname = "hrtimeout_min_us",
+ .data = &hrtimeout_min_us,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = SYSCTL_ONE,
+ .extra2 = &ten_thousand,
+ },
+ {
.procname = "panic",
.data = &panic_timeout,
.maxlen = sizeof(int),
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 5d85014d59b5..50406e057791 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -190,8 +190,9 @@ int clockevents_tick_resume(struct clock_event_device *dev)
#ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST
+int __read_mostly hrtimer_granularity_us = 100;
/* Limit min_delta to a jiffie */
-#define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ)
+#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 f29c00e9709c..b2352612b8ea 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -2393,7 +2393,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) {
@@ -2410,9 +2410,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);
@@ -2434,9 +2433,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.39.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment