*/
struct timespec xtime __attribute__ ((aligned (16)));
struct timespec wall_to_monotonic __attribute__ ((aligned (16)));
+unsigned long last_nsec_offset;
/* Don't completely fail for HZ > 500. */
int tickadj = 500/HZ ? : 1; /* microsecs */
/* in the NTP reference this is called "hardclock()" */
static void update_wall_time_one_tick(void)
{
- long time_adjust_step;
+ long time_adjust_step, delta_nsec;
if ( (time_adjust_step = time_adjust) != 0 ) {
/* We are doing an adjtime thing.
time_adjust_step = tickadj;
else if (time_adjust < -tickadj)
time_adjust_step = -tickadj;
-
+
/* Reduce by this step the amount of time left */
time_adjust -= time_adjust_step;
}
- xtime.tv_nsec += tick_nsec + time_adjust_step * 1000;
+ delta_nsec = tick_nsec + time_adjust_step * 1000;
/*
* Advance the phase, once it gets to one microsecond, then
* advance the tick more.
if (time_phase <= -FINEUSEC) {
long ltemp = -time_phase >> (SHIFT_SCALE - 10);
time_phase += ltemp << (SHIFT_SCALE - 10);
- xtime.tv_nsec -= ltemp;
+ delta_nsec -= ltemp;
}
else if (time_phase >= FINEUSEC) {
long ltemp = time_phase >> (SHIFT_SCALE - 10);
time_phase -= ltemp << (SHIFT_SCALE - 10);
- xtime.tv_nsec += ltemp;
+ delta_nsec += ltemp;
+ }
+ xtime.tv_nsec += delta_nsec;
+
+ /*
+ * The whole point of last_nsec_offset is that it can be updated atomically and
+ * lock-free. Thus, arches that don't have __HAVE_ARCH_CMPXCHG probably can't use
+ * last_nsec_offset anyhow... --davidm 2003-Feb-11
+ */
+#ifdef __HAVE_ARCH_CMPXCHG
+ if (last_nsec_offset > 0) {
+ unsigned long new, old;
+
+ do {
+ old = last_nsec_offset;
+ if (old > delta_nsec)
+ new = old - delta_nsec;
+ else
+ new = 0;
+ } while (cmpxchg(&last_nsec_offset, old, new) != old);
}
+#endif
}
/*
#ifndef ARCH_HAVE_XTIME_LOCK
seqlock_t xtime_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
#endif
-unsigned long last_time_offset;
/*
* This function runs timers and the timer-tq in bottom half context.
wall_jiffies += ticks;
update_wall_time(ticks);
}
- last_time_offset = 0;
calc_load(ticks);
}