/usr/src/lttng-modules-2.7.1/wrapper/trace-clock.h is in lttng-modules-dkms 2.7.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | #ifndef _LTTNG_TRACE_CLOCK_H
#define _LTTNG_TRACE_CLOCK_H
/*
* wrapper/trace-clock.h
*
* Contains LTTng trace clock mapping to LTTng trace clock or mainline monotonic
* clock. This wrapper depends on CONFIG_HIGH_RES_TIMERS=y.
*
* Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; only
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef CONFIG_HAVE_TRACE_CLOCK
#include <linux/trace-clock.h>
#else /* CONFIG_HAVE_TRACE_CLOCK */
#include <linux/hardirq.h>
#include <linux/ktime.h>
#include <linux/time.h>
#include <linux/hrtimer.h>
#include <linux/percpu.h>
#include <linux/version.h>
#include <asm/local.h>
#include "../lttng-kernel-version.h"
#include "percpu-defs.h"
#include "random.h"
#if ((LTTNG_KERNEL_RANGE(3,10,0, 3,10,14) && !LTTNG_RHEL_KERNEL_RANGE(3,10,0,7,0, 3,10,14,0,0)) \
|| LTTNG_KERNEL_RANGE(3,11,0, 3,11,3))
#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."
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
DECLARE_PER_CPU(local_t, lttng_last_tsc);
#if (BITS_PER_LONG == 32)
/*
* Fixup "src_now" using the 32 LSB from "last". We need to handle overflow and
* underflow of the 32nd bit. "last" can be above, below or equal to the 32 LSB
* of "src_now".
*/
static inline u64 trace_clock_fixup(u64 src_now, u32 last)
{
u64 now;
now = src_now & 0xFFFFFFFF00000000ULL;
now |= (u64) last;
/* Detect overflow or underflow between now and last. */
if ((src_now & 0x80000000U) && !(last & 0x80000000U)) {
/*
* If 32nd bit transitions from 1 to 0, and we move forward in
* time from "now" to "last", then we have an overflow.
*/
if (((s32) now - (s32) last) < 0)
now += 0x0000000100000000ULL;
} else if (!(src_now & 0x80000000U) && (last & 0x80000000U)) {
/*
* If 32nd bit transitions from 0 to 1, and we move backward in
* time from "now" to "last", then we have an underflow.
*/
if (((s32) now - (s32) last) > 0)
now -= 0x0000000100000000ULL;
}
return now;
}
#else /* #if (BITS_PER_LONG == 32) */
/*
* The fixup is pretty easy on 64-bit architectures: "last" is a 64-bit
* value, so we can use last directly as current time.
*/
static inline u64 trace_clock_fixup(u64 src_now, u64 last)
{
return last;
}
#endif /* #else #if (BITS_PER_LONG == 32) */
/*
* Sometimes called with preemption enabled. Can be interrupted.
*/
static inline u64 trace_clock_monotonic_wrapper(void)
{
u64 now;
unsigned long last, result;
local_t *last_tsc;
/* Use fast nmi-safe monotonic clock provided by the Linux kernel. */
preempt_disable();
last_tsc = lttng_this_cpu_ptr(<tng_last_tsc);
last = local_read(last_tsc);
/*
* 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 (((long) now - (long) last) < 0)
now = trace_clock_fixup(now, last);
result = local_cmpxchg(last_tsc, last, (unsigned long) 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 trace_clock_fixup(now, result);
}
}
#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) */
static inline u64 trace_clock_monotonic_wrapper(void)
{
ktime_t ktime;
/*
* Refuse to trace from NMIs with this wrapper, because an NMI could
* nest over the xtime write seqlock and deadlock.
*/
if (in_nmi())
return (u64) -EIO;
ktime = ktime_get();
return ktime_to_ns(ktime);
}
#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) */
static inline u64 trace_clock_read64(void)
{
return (u64) trace_clock_monotonic_wrapper();
}
static inline u64 trace_clock_freq(void)
{
return (u64) NSEC_PER_SEC;
}
static inline int trace_clock_uuid(char *uuid)
{
return wrapper_get_bootid(uuid);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0))
static inline int get_trace_clock(void)
{
printk(KERN_WARNING "LTTng: Using mainline kernel monotonic fast clock, which is NMI-safe.\n");
return 0;
}
#else /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) */
static inline int get_trace_clock(void)
{
printk(KERN_WARNING "LTTng: Using mainline kernel monotonic clock. NMIs will not be traced.\n");
return 0;
}
#endif /* #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0)) */
static inline void put_trace_clock(void)
{
}
#endif /* CONFIG_HAVE_TRACE_CLOCK */
#endif /* _LTTNG_TRACE_CLOCK_H */
|