Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 32254
b: refs/heads/master
c: e154ff3
h: refs/heads/master
v: v3
  • Loading branch information
Roman Zippel authored and Linus Torvalds committed Jul 10, 2006
1 parent be9b474 commit 5e9cef3
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 32dd66fce3b0ad5857433433b795844cb397608e
refs/heads/master: e154ff3d2c5ad313ef0c66e6217502361cad2799
85 changes: 47 additions & 38 deletions trunk/kernel/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ int do_settimeofday(struct timespec *tv)
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);

clock->error = 0;
ntp_clear();

write_sequnlock_irqrestore(&xtime_lock, flags);
Expand Down Expand Up @@ -1008,52 +1009,52 @@ static int __init timekeeping_init_device(void)
device_initcall(timekeeping_init_device);

/*
* If the error is already larger, we look ahead another tick,
* If the error is already larger, we look ahead even further
* to compensate for late or lost adjustments.
*/
static __always_inline int clocksource_bigadjust(int sign, s64 error, s64 *interval, s64 *offset)
static __always_inline int clocksource_bigadjust(s64 error, s64 *interval, s64 *offset)
{
int adj;
s64 tick_error, i;
u32 look_ahead, adj;
s32 error2, mult;

/*
* As soon as the machine is synchronized to the external time
* source this should be the common case.
* Use the current error value to determine how much to look ahead.
* The larger the error the slower we adjust for it to avoid problems
* with losing too many ticks, otherwise we would overadjust and
* produce an even larger error. The smaller the adjustment the
* faster we try to adjust for it, as lost ticks can do less harm
* here. This is tuned so that an error of about 1 msec is adusted
* within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
*/
error >>= 2;
if (likely(sign > 0 ? error <= *interval : error >= *interval))
return sign;
error2 = clock->error >> (TICK_LENGTH_SHIFT + 22 - 2 * SHIFT_HZ);
error2 = abs(error2);
for (look_ahead = 0; error2 > 0; look_ahead++)
error2 >>= 2;

/*
* An extra look ahead dampens the effect of the current error,
* which can grow quite large with continously late updates, as
* it would dominate the adjustment value and can lead to
* oscillation.
* Now calculate the error in (1 << look_ahead) ticks, but first
* remove the single look ahead already included in the error.
*/
error += current_tick_length() >> (TICK_LENGTH_SHIFT - clock->shift + 1);
error -= clock->xtime_interval >> 1;

adj = 0;
while (1) {
error >>= 1;
if (sign > 0 ? error <= *interval : error >= *interval)
break;
adj++;
tick_error = current_tick_length() >> (TICK_LENGTH_SHIFT - clock->shift + 1);
tick_error -= clock->xtime_interval >> 1;
error = ((error - tick_error) >> look_ahead) + tick_error;

/* Finally calculate the adjustment shift value. */
i = *interval;
mult = 1;
if (error < 0) {
error = -error;
*interval = -*interval;
*offset = -*offset;
mult = -1;
}

/*
* Add the current adjustments to the error and take the offset
* into account, the latter can cause the error to be hardly
* reduced at the next tick. Check the error again if there's
* room for another adjustment, thus further reducing the error
* which otherwise had to be corrected at the next update.
*/
error = (error << 1) - *interval + *offset;
if (sign > 0 ? error > *interval : error < *interval)
adj++;
for (adj = 0; error > i; adj++)
error >>= 1;

*interval <<= adj;
*offset <<= adj;
return sign << adj;
return mult << adj;
}

/*
Expand All @@ -1068,11 +1069,19 @@ static void clocksource_adjust(struct clocksource *clock, s64 offset)

error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
if (error > interval) {
adj = clocksource_bigadjust(1, error, &interval, &offset);
error >>= 2;
if (likely(error <= interval))
adj = 1;
else
adj = clocksource_bigadjust(error, &interval, &offset);
} else if (error < -interval) {
interval = -interval;
offset = -offset;
adj = clocksource_bigadjust(-1, error, &interval, &offset);
error >>= 2;
if (likely(error >= -interval)) {
adj = -1;
interval = -interval;
offset = -offset;
} else
adj = clocksource_bigadjust(error, &interval, &offset);
} else
return;

Expand Down Expand Up @@ -1129,7 +1138,7 @@ static void update_wall_time(void)
clocksource_adjust(clock, offset);

/* store full nanoseconds into xtime */
xtime.tv_nsec = clock->xtime_nsec >> clock->shift;
xtime.tv_nsec = (s64)clock->xtime_nsec >> clock->shift;
clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;

/* check to see if there is a new clocksource to use */
Expand Down

0 comments on commit 5e9cef3

Please sign in to comment.