Thread (7 messages) flat view 7 messages, 4 authors, 2015-02-13

Re: [PATCH v5] perf: Use monotonic clock as a source for timestamps

From: Peter Zijlstra <hidden>
Date: 2015-02-12 15:38:22
Also in: lkml
Subsystem: the rest, x86 architecture (32-bit and 64-bit) · Maintainers: Linus Torvalds, Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen

Possibly related (same subject, not in this thread)

On Thu, Feb 12, 2015 at 11:28:14AM +0100, Peter Zijlstra wrote:
quoted
and you would have to check the clocksource is TSC.
It implicitly does that; it has that sched_clock_stable() thing, but
yeah I suppose someone could change the clocksource even though the tsc
is stable.

Not using TSC when its available is quite crazy though.. but sure.
Something like this on top then.. it might have a few header issues, the
whole asm/tsc.h vs clocksource.h thing looks like pain.

I haven't tried to compile it, maybe we can move cycle_t into types and
fwd declare struct clocksource or whatnot.

Of course, all this is quite horrible on the timekeeping side; it might
be tglx and/or jstutlz are having spasms just reading it :-)

---
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1967,17 +1967,19 @@ static void local_clock_user_time(struct
 	cyc2ns_read_end(data);
 }
 
-extern void notrace __ktime_get_mono_fast(u64 *offset, u32 *mult, u16 *shift);
+extern bool notrace __ktime_get_mono_fast(cycle_t (*read)(struct clocksource *cs),
+		u64 *offset, u32 *mult, u16 *shift);
 
 static void ktime_fast_mono_user_time(struct perf_event_mmap_page *userpg, u64 now)
 {
+	if (!__ktime_get_mono_fast(read_tsc, &userpg->time_zero,
+				   &userpg->time_mult,
+				   &userpg->time_shift))
+		return;
+
 	userpg->cap_user_time = 1;
 	userpg->cap_user_time_zero = 1;
 
-	__ktime_get_mono_fast(&userpg->time_zero,
-			      &userpg->time_mult,
-			      &userpg->time_shift);
-
 	userpg->offset = userpg->time_zero - now;
 }
 
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -334,7 +334,8 @@ u64 notrace ktime_get_mono_fast_ns(void)
 }
 EXPORT_SYMBOL_GPL(ktime_get_mono_fast_ns);
 
-void notrace __ktime_get_mono_fast(u64 *offset, u32 *mult, u16 *shift)
+bool notrace __ktime_get_mono_fast(cycle_t (*read)(struct clocksource *),
+				   u64 *offset, u32 *mult, u16 *shift)
 {
 	struct tk_read_base *tkr;
 	unsigned int seq;
@@ -345,6 +346,9 @@ void notrace __ktime_get_mono_fast(u64 *
 		seq = raw_read_seqcount(&tk_fast_mono.seq);
 		tkr = tk_fast_mono.base + (seq & 0x01);
 
+		if (tkr->read != read)
+			return false;
+
 		cycle_now = tkr->read(tkr->clock);
 		delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask);
 
@@ -362,6 +366,8 @@ void notrace __ktime_get_mono_fast(u64 *
 		*offset = now - nsec;
 
 	} while (read_seqcount_retry(&tk_fast_mono.seq, seq));
+
+	return true;
 }
 
 #ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index 94605c0e9cee..68e4039a58ea 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -32,6 +32,8 @@ static inline cycles_t get_cycles(void)
 	return ret;
 }
 
+extern void cycle_t read_tsc(struct clocksource *);
+
 static __always_inline cycles_t vget_cycles(void)
 {
 	/*
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 505449700e0c..c580998f0160 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -965,7 +965,7 @@ static struct clocksource clocksource_tsc;
  * checking the result of read_tsc() - cycle_last for being negative.
  * That works because CLOCKSOURCE_MASK(64) does not mask out any bit.
  */
-static cycle_t read_tsc(struct clocksource *cs)
+cycle_t read_tsc(struct clocksource *cs)
 {
 	return (cycle_t)get_cycles();
 }
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help