1 /* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
3 * wrapper/trace-clock.h
5 * Contains LTTng trace clock mapping to LTTng trace clock or mainline monotonic
6 * clock. This wrapper depends on CONFIG_HIGH_RES_TIMERS=y.
8 * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
11 #ifndef _LTTNG_TRACE_CLOCK_H
12 #define _LTTNG_TRACE_CLOCK_H
14 #ifdef CONFIG_HAVE_TRACE_CLOCK
15 #include <linux/trace-clock.h>
16 #else /* CONFIG_HAVE_TRACE_CLOCK */
18 #include <linux/hardirq.h>
19 #include <linux/ktime.h>
20 #include <linux/time.h>
21 #include <linux/hrtimer.h>
22 #include <linux/percpu.h>
23 #include <linux/version.h>
24 #include <asm/local.h>
25 #include <lttng-kernel-version.h>
26 #include <lttng-clock.h>
27 #include <wrapper/compiler.h>
28 #include <wrapper/percpu-defs.h>
29 #include <wrapper/random.h>
31 #if ((LTTNG_KERNEL_RANGE(3,10,0, 3,10,14) && !LTTNG_RHEL_KERNEL_RANGE(3,10,0,123,0,0, 3,10,14,0,0,0)) \
32 || LTTNG_KERNEL_RANGE(3,11,0, 3,11,3))
33 #error "Linux kernels 3.10 and 3.11 introduce a deadlock in the timekeeping subsystem. Fixed by commit 7bd36014460f793c19e7d6c94dab67b0afcfcb7f \"timekeeping: Fix HRTICK related deadlock from ntp lock changes\" in Linux."
36 extern struct lttng_trace_clock
*lttng_trace_clock
;
39 * Upstream Linux commit 27727df240c7 ("Avoid taking lock in NMI path with
40 * CONFIG_DEBUG_TIMEKEEPING") introduces a buggy ktime_get_mono_fast_ns().
41 * This is fixed by patch "timekeeping: Fix __ktime_get_fast_ns() regression".
43 #if (LTTNG_KERNEL_RANGE(4,8,0, 4,8,2) \
44 || LTTNG_KERNEL_RANGE(4,7,4, 4,7,8) \
45 || LTTNG_KERNEL_RANGE(4,4,20, 4,4,25) \
46 || LTTNG_KERNEL_RANGE(4,1,32, 4,1,35))
47 #define LTTNG_CLOCK_NMI_SAFE_BROKEN
51 * We need clock values to be monotonically increasing per-cpu, which is
52 * not strictly guaranteed by ktime_get_mono_fast_ns(). It is
53 * straightforward to do on architectures with a 64-bit cmpxchg(), but
54 * not so on architectures without 64-bit cmpxchg. For now, only enable
55 * this feature on 64-bit architectures.
58 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) \
59 && BITS_PER_LONG == 64 \
60 && !defined(LTTNG_CLOCK_NMI_SAFE_BROKEN))
61 #define LTTNG_USE_NMI_SAFE_CLOCK
64 #ifdef LTTNG_USE_NMI_SAFE_CLOCK
66 DECLARE_PER_CPU(u64
, lttng_last_tsc
);
69 * Sometimes called with preemption enabled. Can be interrupted.
71 static inline u64
trace_clock_monotonic_wrapper(void)
73 u64 now
, last
, result
;
76 /* Use fast nmi-safe monotonic clock provided by the Linux kernel. */
78 last_tsc_ptr
= lttng_this_cpu_ptr(<tng_last_tsc
);
81 * Read "last" before "now". It is not strictly required, but it ensures
82 * that an interrupt coming in won't artificially trigger a case where
83 * "now" < "last". This kind of situation should only happen if the
84 * mono_fast time source goes slightly backwards.
87 now
= ktime_get_mono_fast_ns();
88 if (U64_MAX
/ 2 < now
- last
)
90 result
= cmpxchg64_local(last_tsc_ptr
, last
, now
);
97 * Update not done, due to concurrent update. We can use
98 * "result", since it has been sampled concurrently with our
99 * time read, so it should not be far from "now".
105 #else /* #ifdef LTTNG_USE_NMI_SAFE_CLOCK */
106 static inline u64
trace_clock_monotonic_wrapper(void)
111 * Refuse to trace from NMIs with this wrapper, because an NMI could
112 * nest over the xtime write seqlock and deadlock.
118 return ktime_to_ns(ktime
);
120 #endif /* #else #ifdef LTTNG_USE_NMI_SAFE_CLOCK */
122 static inline u64
trace_clock_read64_monotonic(void)
124 return (u64
) trace_clock_monotonic_wrapper();
127 static inline u64
trace_clock_freq_monotonic(void)
129 return (u64
) NSEC_PER_SEC
;
132 static inline int trace_clock_uuid_monotonic(char *uuid
)
134 return wrapper_get_bootid(uuid
);
137 static inline const char *trace_clock_name_monotonic(void)
142 static inline const char *trace_clock_description_monotonic(void)
144 return "Monotonic Clock";
147 #ifdef LTTNG_USE_NMI_SAFE_CLOCK
148 static inline int get_trace_clock(void)
150 printk_once(KERN_WARNING
"LTTng: Using mainline kernel monotonic fast clock, which is NMI-safe.\n");
153 #else /* #ifdef LTTNG_USE_NMI_SAFE_CLOCK */
154 static inline int get_trace_clock(void)
156 printk_once(KERN_WARNING
"LTTng: Using mainline kernel monotonic clock. NMIs will not be traced.\n");
159 #endif /* #else #ifdef LTTNG_USE_NMI_SAFE_CLOCK */
161 static inline void put_trace_clock(void)
165 static inline u64
trace_clock_read64(void)
167 struct lttng_trace_clock
*ltc
= READ_ONCE(lttng_trace_clock
);
170 return trace_clock_read64_monotonic();
172 read_barrier_depends(); /* load ltc before content */
173 return ltc
->read64();
177 static inline u64
trace_clock_freq(void)
179 struct lttng_trace_clock
*ltc
= READ_ONCE(lttng_trace_clock
);
182 return trace_clock_freq_monotonic();
184 read_barrier_depends(); /* load ltc before content */
189 static inline int trace_clock_uuid(char *uuid
)
191 struct lttng_trace_clock
*ltc
= READ_ONCE(lttng_trace_clock
);
193 read_barrier_depends(); /* load ltc before content */
194 /* Use default UUID cb when NULL */
195 if (!ltc
|| !ltc
->uuid
) {
196 return trace_clock_uuid_monotonic(uuid
);
198 return ltc
->uuid(uuid
);
202 static inline const char *trace_clock_name(void)
204 struct lttng_trace_clock
*ltc
= READ_ONCE(lttng_trace_clock
);
207 return trace_clock_name_monotonic();
209 read_barrier_depends(); /* load ltc before content */
214 static inline const char *trace_clock_description(void)
216 struct lttng_trace_clock
*ltc
= READ_ONCE(lttng_trace_clock
);
219 return trace_clock_description_monotonic();
221 read_barrier_depends(); /* load ltc before content */
222 return ltc
->description();
226 #endif /* CONFIG_HAVE_TRACE_CLOCK */
228 #endif /* _LTTNG_TRACE_CLOCK_H */
This page took 0.034001 seconds and 4 git commands to generate.