-
Notifications
You must be signed in to change notification settings - Fork 0
/
0011-Make-hrtimer-granularity-and-minimum-hrtimeout-confi.patch
executable file
·153 lines (141 loc) · 4.41 KB
/
0011-Make-hrtimer-granularity-and-minimum-hrtimeout-confi.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
From 90451b5e07056637b94758577df2b6a47b11a73b Mon Sep 17 00:00:00 2001
From: Con Kolivas <[email protected]>
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 | 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 7c58ed33e54b..808473f947ee 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
@@ -1097,6 +1099,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 8293ebf4ca08..e4f5b4c483a0 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -2224,7 +2224,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) {
@@ -2241,9 +2241,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);
@@ -2265,9 +2264,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