[PATCH] HZ free ntp
Distangle the NTP update from HZ. This is necessary for dynamic tick enabled kernels. Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> Cc: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
771ee3b04e
commit
f4304ab215
|
@ -286,6 +286,13 @@ static inline void time_interpolator_update(long delta_nsec)
|
|||
|
||||
#define TICK_LENGTH_SHIFT 32
|
||||
|
||||
#ifdef CONFIG_NO_HZ
|
||||
#define NTP_INTERVAL_FREQ (2)
|
||||
#else
|
||||
#define NTP_INTERVAL_FREQ (HZ)
|
||||
#endif
|
||||
#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
|
||||
|
||||
/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
|
||||
extern u64 current_tick_length(void);
|
||||
|
||||
|
|
|
@ -128,15 +128,20 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);
|
|||
static void hrtimer_get_softirq_time(struct hrtimer_base *base)
|
||||
{
|
||||
ktime_t xtim, tomono;
|
||||
struct timespec xts;
|
||||
unsigned long seq;
|
||||
|
||||
do {
|
||||
seq = read_seqbegin(&xtime_lock);
|
||||
xtim = timespec_to_ktime(xtime);
|
||||
tomono = timespec_to_ktime(wall_to_monotonic);
|
||||
|
||||
#ifdef CONFIG_NO_HZ
|
||||
getnstimeofday(&xts);
|
||||
#else
|
||||
xts = xtime;
|
||||
#endif
|
||||
} while (read_seqretry(&xtime_lock, seq));
|
||||
|
||||
xtim = timespec_to_ktime(xts);
|
||||
tomono = timespec_to_ktime(wall_to_monotonic);
|
||||
base[CLOCK_REALTIME].softirq_time = xtim;
|
||||
base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ static u64 tick_length, tick_length_base;
|
|||
|
||||
#define MAX_TICKADJ 500 /* microsecs */
|
||||
#define MAX_TICKADJ_SCALED (((u64)(MAX_TICKADJ * NSEC_PER_USEC) << \
|
||||
TICK_LENGTH_SHIFT) / HZ)
|
||||
TICK_LENGTH_SHIFT) / NTP_INTERVAL_FREQ)
|
||||
|
||||
/*
|
||||
* phase-lock loop variables
|
||||
|
@ -46,13 +46,17 @@ long time_adjust;
|
|||
|
||||
static void ntp_update_frequency(void)
|
||||
{
|
||||
tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT;
|
||||
tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
|
||||
tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
|
||||
u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
|
||||
<< TICK_LENGTH_SHIFT;
|
||||
second_length += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT;
|
||||
second_length += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC);
|
||||
|
||||
do_div(tick_length_base, HZ);
|
||||
tick_length_base = second_length;
|
||||
|
||||
tick_nsec = tick_length_base >> TICK_LENGTH_SHIFT;
|
||||
do_div(second_length, HZ);
|
||||
tick_nsec = second_length >> TICK_LENGTH_SHIFT;
|
||||
|
||||
do_div(tick_length_base, NTP_INTERVAL_FREQ);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,7 +166,7 @@ void second_overflow(void)
|
|||
tick_length -= MAX_TICKADJ_SCALED;
|
||||
} else {
|
||||
tick_length += (s64)(time_adjust * NSEC_PER_USEC /
|
||||
HZ) << TICK_LENGTH_SHIFT;
|
||||
NTP_INTERVAL_FREQ) << TICK_LENGTH_SHIFT;
|
||||
time_adjust = 0;
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +243,8 @@ int do_adjtimex(struct timex *txc)
|
|||
result = -EINVAL;
|
||||
goto leave;
|
||||
}
|
||||
time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC);
|
||||
time_freq = ((s64)txc->freq * NSEC_PER_USEC)
|
||||
>> (SHIFT_USEC - SHIFT_NSEC);
|
||||
}
|
||||
|
||||
if (txc->modes & ADJ_MAXERROR) {
|
||||
|
@ -309,7 +314,8 @@ int do_adjtimex(struct timex *txc)
|
|||
freq_adj += time_freq;
|
||||
freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
|
||||
time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
|
||||
time_offset = (time_offset / HZ) << SHIFT_UPDATE;
|
||||
time_offset = (time_offset / NTP_INTERVAL_FREQ)
|
||||
<< SHIFT_UPDATE;
|
||||
} /* STA_PLL */
|
||||
} /* txc->modes & ADJ_OFFSET */
|
||||
if (txc->modes & ADJ_TICK)
|
||||
|
@ -324,8 +330,10 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
|
|||
if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
|
||||
txc->offset = save_adjust;
|
||||
else
|
||||
txc->offset = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000;
|
||||
txc->freq = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC);
|
||||
txc->offset = shift_right(time_offset, SHIFT_UPDATE)
|
||||
* NTP_INTERVAL_FREQ / 1000;
|
||||
txc->freq = (time_freq / NSEC_PER_USEC)
|
||||
<< (SHIFT_USEC - SHIFT_NSEC);
|
||||
txc->maxerror = time_maxerror;
|
||||
txc->esterror = time_esterror;
|
||||
txc->status = time_status;
|
||||
|
|
|
@ -890,7 +890,7 @@ void __init timekeeping_init(void)
|
|||
ntp_clear();
|
||||
|
||||
clock = clocksource_get_next();
|
||||
clocksource_calculate_interval(clock, tick_nsec);
|
||||
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
|
||||
clock->cycle_last = clocksource_read(clock);
|
||||
|
||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
||||
|
@ -1092,7 +1092,7 @@ static void update_wall_time(void)
|
|||
if (change_clocksource()) {
|
||||
clock->error = 0;
|
||||
clock->xtime_nsec = 0;
|
||||
clocksource_calculate_interval(clock, tick_nsec);
|
||||
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue