linux/kernel/time
Thomas Gleixner 4396e058c5 timekeeping: Provide fast and NMI safe access to CLOCK_MONOTONIC
Tracers want a correlated time between the kernel instrumentation and
user space. We really do not want to export sched_clock() to user
space, so we need to provide something sensible for this.

Using separate data structures with an non blocking sequence count
based update mechanism allows us to do that. The data structure
required for the readout has a sequence counter and two copies of the
timekeeping data.

On the update side:

  smp_wmb();
  tkf->seq++;
  smp_wmb();
  update(tkf->base[0], tk);
  smp_wmb();
  tkf->seq++;
  smp_wmb();
  update(tkf->base[1], tk);

On the reader side:

  do {
     seq = tkf->seq;
     smp_rmb();
     idx = seq & 0x01;
     now = now(tkf->base[idx]);
     smp_rmb();
  } while (seq != tkf->seq)

So if a NMI hits the update of base[0] it will use base[1] which is
still consistent, but this timestamp is not guaranteed to be monotonic
across an update.

The timestamp is calculated by:

	now = base_mono + clock_delta * slope

So if the update lowers the slope, readers who are forced to the
not yet updated second array are still using the old steeper slope.

 tmono
 ^
 |    o  n
 |   o n
 |  u
 | o
 |o
 |12345678---> reader order

 o = old slope
 u = update
 n = new slope

So reader 6 will observe time going backwards versus reader 5.

While other CPUs are likely to be able observe that, the only way
for a CPU local observation is when an NMI hits in the middle of
the update. Timestamps taken from that NMI context might be ahead
of the following timestamps. Callers need to be aware of that and
deal with it.

V2: Got rid of clock monotonic raw and reorganized the data
    structures. Folded in the barrier fix from Mathieu.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
2014-07-23 15:01:55 -07:00
..
alarmtimer.c alarmtimer: return EINVAL instead of ENOTSUPP if rtcdev doesn't exist 2013-10-18 16:23:58 -07:00
clockevents.c time: Change the return type of clockevents_notify() to integer 2014-02-07 15:34:29 +01:00
clocksource.c clocksource: Make delta calculation a function 2014-07-23 15:01:51 -07:00
hrtimer.c time: Consolidate the time accessor prototypes 2014-07-23 10:17:54 -07:00
itimer.c time/timers: Move all time(r) related files into kernel/time 2014-06-23 11:22:35 +02:00
jiffies.c time: Fix overflow when HZ is smaller than 60 2014-02-06 16:01:40 +01:00
Kconfig clocksource: Move cycle_last validation to core code 2014-07-23 15:01:51 -07:00
Makefile kernel: time: Add udelay_test module to validate udelay 2014-07-23 10:16:35 -07:00
ntp_internal.h timekeeping: Convert timekeeping core to use timespec64s 2014-07-23 10:17:54 -07:00
ntp.c timekeeping: Provide timespec64 based interfaces 2014-07-23 10:17:55 -07:00
posix-clock.c kernel: Fix files explicitly needing EXPORT_SYMBOL infrastructure 2011-10-31 19:30:05 -04:00
posix-cpu-timers.c time/timers: Move all time(r) related files into kernel/time 2014-06-23 11:22:35 +02:00
posix-timers.c time: Consolidate the time accessor prototypes 2014-07-23 10:17:54 -07:00
sched_clock.c sched_clock: Remove deprecated setup_sched_clock() API 2014-04-22 13:38:33 -07:00
tick-broadcast-hrtimer.c tick: Fixup more fallout from hrtimer broadcast mode 2014-02-09 15:11:47 +01:00
tick-broadcast.c Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-04-01 11:00:07 -07:00
tick-common.c tick-common: Fix wrong check in tick_check_replacement() 2014-04-15 20:26:44 +02:00
tick-internal.h time: Consolidate the time accessor prototypes 2014-07-23 10:17:54 -07:00
tick-oneshot.c clockevents: Make minimum delay adjustments configurable 2011-09-08 11:10:56 +02:00
tick-sched.c tick-sched: Check tick_nohz_enabled in tick_nohz_switch_to_nohz() 2014-04-15 20:26:58 +02:00
time.c time: Export nsecs_to_jiffies() 2014-07-23 10:18:04 -07:00
timeconst.bc time/timers: Move all time(r) related files into kernel/time 2014-06-23 11:22:35 +02:00
timeconv.c time: add function to convert between calendar time and broken-down time for universal use 2009-09-24 07:20:56 -07:00
timekeeping_debug.c timekeeping: Convert timekeeping core to use timespec64s 2014-07-23 10:17:54 -07:00
timekeeping_internal.h clocksource: Move cycle_last validation to core code 2014-07-23 15:01:51 -07:00
timekeeping.c timekeeping: Provide fast and NMI safe access to CLOCK_MONOTONIC 2014-07-23 15:01:55 -07:00
timekeeping.h time: Consolidate the time accessor prototypes 2014-07-23 10:17:54 -07:00
timer_list.c timer_list: correct the iterator for timer_list 2013-08-28 19:26:38 -07:00
timer_stats.c timer stats: Add a 'Collection: active/inactive' line to timer usage statistics 2013-10-10 09:59:25 +02:00
timer.c timer: Kick dynticks targets on mod_timer*() calls 2014-06-23 11:23:47 +02:00
udelay_test.c kernel: time: Add udelay_test module to validate udelay 2014-07-23 10:16:35 -07:00