+extern struct lttng_trace_clock *lttng_trace_clock;
+
+/*
+ * Upstream Linux commit 27727df240c7 ("Avoid taking lock in NMI path with
+ * CONFIG_DEBUG_TIMEKEEPING") introduces a buggy ktime_get_mono_fast_ns().
+ * This is fixed by patch "timekeeping: Fix __ktime_get_fast_ns() regression".
+ */
+#if (LTTNG_KERNEL_RANGE(4,8,0, 4,8,2) \
+ || LTTNG_KERNEL_RANGE(4,7,4, 4,7,8) \
+ || LTTNG_KERNEL_RANGE(4,4,20, 4,4,25) \
+ || LTTNG_KERNEL_RANGE(4,1,32, 4,1,35))
+#define LTTNG_CLOCK_NMI_SAFE_BROKEN
+#endif
+
+/*
+ * We need clock values to be monotonically increasing per-cpu, which is
+ * not strictly guaranteed by ktime_get_mono_fast_ns(). It is
+ * straightforward to do on architectures with a 64-bit cmpxchg(), but
+ * not so on architectures without 64-bit cmpxchg. For now, only enable
+ * this feature on 64-bit architectures.
+ */
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) \
+ && BITS_PER_LONG == 64 \
+ && !defined(LTTNG_CLOCK_NMI_SAFE_BROKEN))
+#define LTTNG_USE_NMI_SAFE_CLOCK
+#endif
+
+#ifdef LTTNG_USE_NMI_SAFE_CLOCK
+
+DECLARE_PER_CPU(u64, lttng_last_tsc);
+
+/*
+ * Sometimes called with preemption enabled. Can be interrupted.
+ */
+static inline u64 trace_clock_monotonic_wrapper(void)
+{
+ u64 now, last, result;
+ u64 *last_tsc_ptr;
+
+ /* Use fast nmi-safe monotonic clock provided by the Linux kernel. */
+ preempt_disable();
+ last_tsc_ptr = lttng_this_cpu_ptr(<tng_last_tsc);
+ last = *last_tsc_ptr;
+ /*
+ * Read "last" before "now". It is not strictly required, but it ensures
+ * that an interrupt coming in won't artificially trigger a case where
+ * "now" < "last". This kind of situation should only happen if the
+ * mono_fast time source goes slightly backwards.
+ */
+ barrier();
+ now = ktime_get_mono_fast_ns();
+ if (U64_MAX / 2 < now - last)
+ now = last;
+ result = cmpxchg64_local(last_tsc_ptr, last, now);
+ preempt_enable();
+ if (result == last) {
+ /* Update done. */
+ return now;
+ } else {
+ /*
+ * Update not done, due to concurrent update. We can use
+ * "result", since it has been sampled concurrently with our
+ * time read, so it should not be far from "now".
+ */
+ return result;
+ }
+}
+
+#else /* #ifdef LTTNG_USE_NMI_SAFE_CLOCK */