* [PATCH v2] ARM: sched_clock: Load cycle count after epoch stabilizes
@ 2013-06-17 22:40 Stephen Boyd
2013-06-17 22:58 ` John Stultz
0 siblings, 1 reply; 2+ messages in thread
From: Stephen Boyd @ 2013-06-17 22:40 UTC (permalink / raw)
To: linux-arm-kernel
There is a small race between when the cycle count is read from
the hardware and when the epoch stabilizes. Consider this
scenario:
CPU0 CPU1
---- ----
cyc = read_sched_clock()
cyc_to_sched_clock()
update_sched_clock()
...
cd.epoch_cyc = cyc;
epoch_cyc = cd.epoch_cyc;
...
epoch_ns + cyc_to_ns((cyc - epoch_cyc)
The cyc on cpu0 was read before the epoch changed. But we
calculate the nanoseconds based on the new epoch by subtracting
the new epoch from the old cycle count. Since epoch is most likely
larger than the old cycle count we calculate a large number that
will be converted to nanoseconds and added to epoch_ns, causing
time to jump forward too much.
Fix this problem by reading the hardware after the epoch has
stabilized.
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
kernel/time/sched_clock.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index aad1ae6..a326f27 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -49,10 +49,14 @@ static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
return (cyc * mult) >> shift;
}
-static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask)
+static unsigned long long notrace sched_clock_32(void)
{
u64 epoch_ns;
u32 epoch_cyc;
+ u32 cyc;
+
+ if (cd.suspended)
+ return cd.epoch_ns;
/*
* Load the epoch_cyc and epoch_ns atomically. We do this by
@@ -68,7 +72,9 @@ static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask)
smp_rmb();
} while (epoch_cyc != cd.epoch_cyc_copy);
- return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, cd.mult, cd.shift);
+ cyc = read_sched_clock();
+ cyc = (cyc - epoch_cyc) & sched_clock_mask;
+ return epoch_ns + cyc_to_ns(cyc, cd.mult, cd.shift);
}
/*
@@ -160,19 +166,10 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
pr_debug("Registered %pF as sched_clock source\n", read);
}
-static unsigned long long notrace sched_clock_32(void)
-{
- u32 cyc = read_sched_clock();
- return cyc_to_sched_clock(cyc, sched_clock_mask);
-}
-
unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32;
unsigned long long notrace sched_clock(void)
{
- if (cd.suspended)
- return cd.epoch_ns;
-
return sched_clock_func();
}
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH v2] ARM: sched_clock: Load cycle count after epoch stabilizes
2013-06-17 22:40 [PATCH v2] ARM: sched_clock: Load cycle count after epoch stabilizes Stephen Boyd
@ 2013-06-17 22:58 ` John Stultz
0 siblings, 0 replies; 2+ messages in thread
From: John Stultz @ 2013-06-17 22:58 UTC (permalink / raw)
To: linux-arm-kernel
On 06/17/2013 03:40 PM, Stephen Boyd wrote:
> There is a small race between when the cycle count is read from
> the hardware and when the epoch stabilizes. Consider this
> scenario:
>
> CPU0 CPU1
> ---- ----
> cyc = read_sched_clock()
> cyc_to_sched_clock()
> update_sched_clock()
> ...
> cd.epoch_cyc = cyc;
> epoch_cyc = cd.epoch_cyc;
> ...
> epoch_ns + cyc_to_ns((cyc - epoch_cyc)
>
> The cyc on cpu0 was read before the epoch changed. But we
> calculate the nanoseconds based on the new epoch by subtracting
> the new epoch from the old cycle count. Since epoch is most likely
> larger than the old cycle count we calculate a large number that
> will be converted to nanoseconds and added to epoch_ns, causing
> time to jump forward too much.
>
> Fix this problem by reading the hardware after the epoch has
> stabilized.
>
> Cc: Russell King <linux@arm.linux.org.uk>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Thanks for the resend here.
I've got this in my tree and unless I get an objection in the next day
or so, I'll send it on to Thomas.
thanks
-john
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-06-17 22:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-17 22:40 [PATCH v2] ARM: sched_clock: Load cycle count after epoch stabilizes Stephen Boyd
2013-06-17 22:58 ` John Stultz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).