Skip to content

Commit a08ca5d

Browse files
bebarinojohnstultz-work
authored andcommitted
sched_clock: Use an hrtimer instead of timer
In the next patch we're going to increase the number of bits that the generic sched_clock can handle to be greater than 32. With more than 32 bits the wraparound time can be larger than what can fit into the units that msecs_to_jiffies takes (unsigned int). Luckily, the wraparound is initially calculated in nanoseconds which we can easily use with hrtimers, so switch to using an hrtimer. Cc: Russell King <linux@arm.linux.org.uk> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> [jstultz: Fixup hrtimer intitialization order issue] Signed-off-by: John Stultz <john.stultz@linaro.org>
1 parent 85c3d2d commit a08ca5d

File tree

1 file changed

+21
-17
lines changed

1 file changed

+21
-17
lines changed

kernel/time/sched_clock.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@
88
#include <linux/clocksource.h>
99
#include <linux/init.h>
1010
#include <linux/jiffies.h>
11+
#include <linux/ktime.h>
1112
#include <linux/kernel.h>
1213
#include <linux/moduleparam.h>
1314
#include <linux/sched.h>
1415
#include <linux/syscore_ops.h>
15-
#include <linux/timer.h>
16+
#include <linux/hrtimer.h>
1617
#include <linux/sched_clock.h>
1718
#include <linux/seqlock.h>
1819

1920
struct clock_data {
21+
ktime_t wrap_kt;
2022
u64 epoch_ns;
2123
u32 epoch_cyc;
2224
seqcount_t seq;
@@ -26,8 +28,7 @@ struct clock_data {
2628
bool suspended;
2729
};
2830

29-
static void sched_clock_poll(unsigned long wrap_ticks);
30-
static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
31+
static struct hrtimer sched_clock_timer;
3132
static int irqtime = -1;
3233

3334
core_param(irqtime, irqtime, int, 0400);
@@ -93,15 +94,16 @@ static void notrace update_sched_clock(void)
9394
raw_local_irq_restore(flags);
9495
}
9596

96-
static void sched_clock_poll(unsigned long wrap_ticks)
97+
static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
9798
{
98-
mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks));
9999
update_sched_clock();
100+
hrtimer_forward_now(hrt, cd.wrap_kt);
101+
return HRTIMER_RESTART;
100102
}
101103

102104
void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
103105
{
104-
unsigned long r, w;
106+
unsigned long r;
105107
u64 res, wrap;
106108
char r_unit;
107109

@@ -129,19 +131,13 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
129131

130132
/* calculate how many ns until we wrap */
131133
wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift);
132-
do_div(wrap, NSEC_PER_MSEC);
133-
w = wrap;
134+
cd.wrap_kt = ns_to_ktime(wrap - (wrap >> 3));
134135

135136
/* calculate the ns resolution of this counter */
136137
res = cyc_to_ns(1ULL, cd.mult, cd.shift);
137-
pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n",
138-
bits, r, r_unit, res, w);
138+
pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
139+
bits, r, r_unit, res, wrap);
139140

140-
/*
141-
* Start the timer to keep sched_clock() properly updated and
142-
* sets the initial epoch.
143-
*/
144-
sched_clock_timer.data = msecs_to_jiffies(w - (w / 10));
145141
update_sched_clock();
146142

147143
/*
@@ -172,12 +168,20 @@ void __init sched_clock_postinit(void)
172168
if (read_sched_clock == jiffy_sched_clock_read)
173169
setup_sched_clock(jiffy_sched_clock_read, 32, HZ);
174170

175-
sched_clock_poll(sched_clock_timer.data);
171+
update_sched_clock();
172+
173+
/*
174+
* Start the timer to keep sched_clock() properly updated and
175+
* sets the initial epoch.
176+
*/
177+
hrtimer_init(&sched_clock_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
178+
sched_clock_timer.function = sched_clock_poll;
179+
hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL);
176180
}
177181

178182
static int sched_clock_suspend(void)
179183
{
180-
sched_clock_poll(sched_clock_timer.data);
184+
sched_clock_poll(&sched_clock_timer);
181185
cd.suspended = true;
182186
return 0;
183187
}

0 commit comments

Comments
 (0)