[PATCH] ARM: sched_clock: fix the timing of reading current clock cycles in cyc_to_sched_clock.

katsuki.uwatoko at toshiba.co.jp katsuki.uwatoko at toshiba.co.jp
Thu Jul 12 23:16:06 EDT 2012


The current clock cycle (cyc) must be read after epoc_cyc and epoch_ns
are fixed.  The calculation result gets invalid when epoch_cyc is
updated after cyc is determined, because the result of (cyc -
epoch_cyc) is unsigned int.

Signed-off-by: UWATOKO Katsuki <katsuki.uwatoko at toshiba.co.jp>
---
 arch/arm/kernel/sched_clock.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
index 27d186a..ab08671 100644
--- a/arch/arm/kernel/sched_clock.c
+++ b/arch/arm/kernel/sched_clock.c
@@ -44,7 +44,7 @@ static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
 	return (cyc * mult) >> shift;
 }
 
-static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask)
+static unsigned long long cyc_to_sched_clock(u32 (*read)(void), u32 mask)
 {
 	u64 epoch_ns;
 	u32 epoch_cyc;
@@ -63,7 +63,8 @@ static unsigned long long 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);
+	return epoch_ns + cyc_to_ns((read() - epoch_cyc) & mask, cd.mult,
+				    cd.shift);
 }
 
 /*
@@ -150,8 +151,7 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 
 unsigned long long notrace sched_clock(void)
 {
-	u32 cyc = read_sched_clock();
-	return cyc_to_sched_clock(cyc, sched_clock_mask);
+	return cyc_to_sched_clock(read_sched_clock, sched_clock_mask);
 }
 
 void __init sched_clock_postinit(void)
-- 
1.7.4.1




More information about the linux-arm-kernel mailing list