Commit 1ac38088 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] wall_to_monotonic initialization fixes for

From: Tim Schmielau <tim@physik3.uni-rostock.de>

This patch adds (or fixes) initialization of wall_to_monotonic for a few
more architectures.

This should get rid of the strange uptime>14600 days reports, except on arm
whose arch file layout is too unfamiliar to me.

The patch is blessed by George Anzinger, but untested due to lack of
hardware.
parent 9ed052e6
...@@ -451,8 +451,9 @@ do_gettimeofday(struct timeval *tv) ...@@ -451,8 +451,9 @@ do_gettimeofday(struct timeval *tv)
int int
do_settimeofday(struct timespec *tv) do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
unsigned long delta_nsec; unsigned long delta_nsec;
long sec, nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -474,31 +475,19 @@ do_settimeofday(struct timespec *tv) ...@@ -474,31 +475,19 @@ do_settimeofday(struct timespec *tv)
delta_nsec *= 1000; delta_nsec *= 1000;
#endif #endif
sec = tv->tv_sec;
nsec = tv->tv_nsec;
nsec -= delta_nsec; nsec -= delta_nsec;
if (nsec < 0) {
nsec += NSEC_PER_SEC;
sec -= 1;
}
xtime.tv_sec = sec; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
xtime.tv_nsec = nsec; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT;
wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
wall_to_monotonic.tv_sec++;
} else if (wall_to_monotonic.tv_nsec < 0) {
wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
wall_to_monotonic.tv_sec--;
}
write_sequnlock_irq(&xtime_lock); write_sequnlock_irq(&xtime_lock);
return 0; return 0;
} }
......
...@@ -115,6 +115,9 @@ void do_gettimeofday(struct timeval *tv) ...@@ -115,6 +115,9 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -125,28 +128,15 @@ int do_settimeofday(struct timespec *tv) ...@@ -125,28 +128,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* made, and then undo it! * made, and then undo it!
*/ */
tv->tv_nsec -= cur_timer->get_offset() * NSEC_PER_USEC; nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC; nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) { set_normalized_timespec(&xtime, sec, nsec);
wall_to_monotonic.tv_nsec -= NSEC_PER_SEC; set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
wall_to_monotonic.tv_sec++;
}
if (wall_to_monotonic.tv_nsec < 0) {
wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
wall_to_monotonic.tv_sec--;
}
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
......
...@@ -104,21 +104,6 @@ static struct time_interpolator itc_interpolator = { ...@@ -104,21 +104,6 @@ static struct time_interpolator itc_interpolator = {
.reset = itc_reset .reset = itc_reset
}; };
static inline void
set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
{
while (nsec > NSEC_PER_SEC) {
nsec -= NSEC_PER_SEC;
++sec;
}
while (nsec < 0) {
nsec += NSEC_PER_SEC;
--sec;
}
ts->tv_sec = sec;
ts->tv_nsec = nsec;
}
int int
do_settimeofday (struct timespec *tv) do_settimeofday (struct timespec *tv)
{ {
......
...@@ -103,6 +103,7 @@ void time_init(void) ...@@ -103,6 +103,7 @@ void time_init(void)
time.tm_hour, time.tm_min, time.tm_sec); time.tm_hour, time.tm_min, time.tm_sec);
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
} }
wall_to_monotonic.tv_sec = -xtime.tv_sec;
mach_sched_init(timer_interrupt); mach_sched_init(timer_interrupt);
} }
...@@ -140,6 +141,8 @@ void do_gettimeofday(struct timeval *tv) ...@@ -140,6 +141,8 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
extern unsigned long wall_jiffies; extern unsigned long wall_jiffies;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
...@@ -152,16 +155,15 @@ int do_settimeofday(struct timespec *tv) ...@@ -152,16 +155,15 @@ int do_settimeofday(struct timespec *tv)
* Discover what correction gettimeofday * Discover what correction gettimeofday
* would have done, and then undo it! * would have done, and then undo it!
*/ */
tv->tv_nsec -= 1000 * (mach_gettimeoffset() + nsec -= 1000 * (mach_gettimeoffset() +
(jiffies - wall_jiffies) * (1000000 / HZ)); (jiffies - wall_jiffies) * (1000000 / HZ));
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
......
...@@ -131,6 +131,7 @@ void time_init(void) ...@@ -131,6 +131,7 @@ void time_init(void)
year += 100; year += 100;
xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
wall_to_monotonic.tv_sec = -xtime.tv_sec;
mach_sched_init(timer_interrupt); mach_sched_init(timer_interrupt);
} }
...@@ -165,6 +166,9 @@ void do_gettimeofday(struct timeval *tv) ...@@ -165,6 +166,9 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -177,15 +181,14 @@ int do_settimeofday(struct timespec *tv) ...@@ -177,15 +181,14 @@ int do_settimeofday(struct timespec *tv)
* would have done, and then undo it! * would have done, and then undo it!
*/ */
if (mach_gettimeoffset) if (mach_gettimeoffset)
tv->tv_nsec -= (mach_gettimeoffset() * 1000); nsec -= (mach_gettimeoffset() * 1000);
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
......
...@@ -98,6 +98,9 @@ void do_gettimeofday(struct timeval *tv) ...@@ -98,6 +98,9 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -108,16 +111,15 @@ int do_settimeofday(struct timespec *tv) ...@@ -108,16 +111,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* made, and then undo it! * made, and then undo it!
*/ */
tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC; nsec -= do_gettimeoffset() * NSEC_PER_USEC;
tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC; nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
...@@ -500,6 +502,9 @@ void __init time_init(void) ...@@ -500,6 +502,9 @@ void __init time_init(void)
xtime.tv_sec = rtc_get_time(); xtime.tv_sec = rtc_get_time();
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
/* choose appropriate gettimeoffset routine */ /* choose appropriate gettimeoffset routine */
if (!cpu_has_counter) { if (!cpu_has_counter) {
/* no cpu counter - sorry */ /* no cpu counter - sorry */
......
...@@ -98,6 +98,9 @@ void do_gettimeofday(struct timeval *tv) ...@@ -98,6 +98,9 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -108,16 +111,15 @@ int do_settimeofday(struct timespec *tv) ...@@ -108,16 +111,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* made, and then undo it! * made, and then undo it!
*/ */
tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC; nsec -= do_gettimeoffset() * NSEC_PER_USEC;
tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC; nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - tsec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
...@@ -499,6 +501,8 @@ void __init time_init(void) ...@@ -499,6 +501,8 @@ void __init time_init(void)
xtime.tv_sec = rtc_get_time(); xtime.tv_sec = rtc_get_time();
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
/* choose appropriate gettimeoffset routine */ /* choose appropriate gettimeoffset routine */
if (!cpu_has_counter) { if (!cpu_has_counter) {
......
...@@ -190,6 +190,9 @@ do_gettimeofday (struct timeval *tv) ...@@ -190,6 +190,9 @@ do_gettimeofday (struct timeval *tv)
int int
do_settimeofday (struct timespec *tv) do_settimeofday (struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -202,16 +205,15 @@ do_settimeofday (struct timespec *tv) ...@@ -202,16 +205,15 @@ do_settimeofday (struct timespec *tv)
* Discover what correction gettimeofday would have * Discover what correction gettimeofday would have
* done, and then undo it! * done, and then undo it!
*/ */
tv->tv_nsec -= gettimeoffset() * 1000; nsec -= gettimeoffset() * 1000;
tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ); nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
...@@ -243,6 +245,8 @@ void __init time_init(void) ...@@ -243,6 +245,8 @@ void __init time_init(void)
write_seqlock_irq(&xtime_lock); write_seqlock_irq(&xtime_lock);
xtime.tv_sec = tod_data.tod_sec; xtime.tv_sec = tod_data.tod_sec;
xtime.tv_nsec = tod_data.tod_usec * 1000; xtime.tv_nsec = tod_data.tod_usec * 1000;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irq(&xtime_lock); write_sequnlock_irq(&xtime_lock);
} else { } else {
printk(KERN_ERR "Error reading tod clock\n"); printk(KERN_ERR "Error reading tod clock\n");
......
...@@ -241,6 +241,8 @@ void do_gettimeofday(struct timeval *tv) ...@@ -241,6 +241,8 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, new_sec = tv->tv_sec;
long wtm_nsec, new_nsec = tv->tv_nsec;
unsigned long flags; unsigned long flags;
int tb_delta, new_nsec, new_sec; int tb_delta, new_nsec, new_sec;
...@@ -268,14 +270,14 @@ int do_settimeofday(struct timespec *tv) ...@@ -268,14 +270,14 @@ int do_settimeofday(struct timespec *tv)
*/ */
tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id())); tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy; tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
new_sec = tv->tv_sec;
new_nsec = tv->tv_nsec - 1000 * mulhwu(tb_to_us, tb_delta); new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
while (new_nsec < 0) {
new_sec--; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
new_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
}
xtime.tv_nsec = new_nsec; set_normalized_timespec(&xtime, new_sec, new_nsec);
xtime.tv_sec = new_sec; set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
/* In case of a large backwards jump in time with NTP, we want the /* In case of a large backwards jump in time with NTP, we want the
* clock to be updated as soon as the PLL is again in lock. * clock to be updated as soon as the PLL is again in lock.
...@@ -347,6 +349,8 @@ void __init time_init(void) ...@@ -347,6 +349,8 @@ void __init time_init(void)
sys_tz.tz_dsttime = 0; sys_tz.tz_dsttime = 0;
xtime.tv_sec -= time_offset; xtime.tv_sec -= time_offset;
} }
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
} }
#define FEBRUARY 2 #define FEBRUARY 2
......
...@@ -339,9 +339,11 @@ void do_gettimeofday(struct timeval *tv) ...@@ -339,9 +339,11 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, new_sec = tv->tv_sec;
long wtm_nsec, new_nsec = tv->tv_nsec;
unsigned long flags; unsigned long flags;
unsigned long delta_xsec; unsigned long delta_xsec;
long int tb_delta, new_nsec, new_sec; long int tb_delta;
unsigned long new_xsec; unsigned long new_xsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
...@@ -364,14 +366,13 @@ int do_settimeofday(struct timespec *tv) ...@@ -364,14 +366,13 @@ int do_settimeofday(struct timespec *tv)
tb_delta = tb_ticks_since(tb_last_stamp); tb_delta = tb_ticks_since(tb_last_stamp);
tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy; tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
new_sec = tv->tv_sec; new_nsec -= tb_delta / tb_ticks_per_usec / 1000;
new_nsec = tv->tv_nsec - (tb_delta / tb_ticks_per_usec / 1000);
while (new_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
new_sec--; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
new_nsec += NSEC_PER_SEC;
} set_normalized_timespec(&xtime, new_sec, new_nsec);
xtime.tv_nsec = new_nsec; set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = new_sec;
/* In case of a large backwards jump in time with NTP, we want the /* In case of a large backwards jump in time with NTP, we want the
* clock to be updated as soon as the PLL is again in lock. * clock to be updated as soon as the PLL is again in lock.
...@@ -484,6 +485,8 @@ void __init time_init(void) ...@@ -484,6 +485,8 @@ void __init time_init(void)
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
last_rtc_update = xtime.tv_sec; last_rtc_update = xtime.tv_sec;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irqrestore(&xtime_lock, flags); write_sequnlock_irqrestore(&xtime_lock, flags);
/* Not exact, but the timer interrupt takes care of this */ /* Not exact, but the timer interrupt takes care of this */
......
...@@ -104,6 +104,9 @@ void do_gettimeofday(struct timeval *tv) ...@@ -104,6 +104,9 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -114,15 +117,14 @@ int do_settimeofday(struct timespec *tv) ...@@ -114,15 +117,14 @@ int do_settimeofday(struct timespec *tv)
* Discover what correction gettimeofday * Discover what correction gettimeofday
* would have done, and then undo it! * would have done, and then undo it!
*/ */
tv->tv_nsec -= do_gettimeoffset() * 1000; nsec -= do_gettimeoffset() * 1000;
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
...@@ -263,6 +265,8 @@ void __init time_init(void) ...@@ -263,6 +265,8 @@ void __init time_init(void)
set_time_cc = init_timer_cc - 0x8126d60e46000000LL + set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
(0x3c26700LL*1000000*4096); (0x3c26700LL*1000000*4096);
tod_to_timeval(set_time_cc, &xtime); tod_to_timeval(set_time_cc, &xtime);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
/* request the 0x1004 external interrupt */ /* request the 0x1004 external interrupt */
if (register_early_external_interrupt(0x1004, do_comparator_interrupt, if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
......
...@@ -179,6 +179,9 @@ void do_gettimeofday(struct timeval *tv) ...@@ -179,6 +179,9 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -189,16 +192,15 @@ int do_settimeofday(struct timespec *tv) ...@@ -189,16 +192,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* made, and then undo it! * made, and then undo it!
*/ */
tv->tv_nsec -= 1000 * (do_gettimeoffset() + nsec -= 1000 * (do_gettimeoffset() +
(jiffies - wall_jiffies) * (1000000 / HZ)); (jiffies - wall_jiffies) * (1000000 / HZ));
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
} set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
...@@ -418,6 +420,9 @@ void __init time_init(void) ...@@ -418,6 +420,9 @@ void __init time_init(void)
rtc_get_time(&xtime); rtc_get_time(&xtime);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
if (board_timer_setup) { if (board_timer_setup) {
board_timer_setup(&irq0); board_timer_setup(&irq0);
} else { } else {
......
...@@ -408,9 +408,9 @@ void __init sbus_time_init(void) ...@@ -408,9 +408,9 @@ void __init sbus_time_init(void)
mon = MSTK_REG_MONTH(mregs); mon = MSTK_REG_MONTH(mregs);
year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
wall_to_monotonic.tv_nsec = -xtime.tv_nsec; set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
mregs->creg &= ~MSTK_CREG_READ; mregs->creg &= ~MSTK_CREG_READ;
spin_unlock_irq(&mostek_lock); spin_unlock_irq(&mostek_lock);
#ifdef CONFIG_SUN4 #ifdef CONFIG_SUN4
...@@ -441,9 +441,9 @@ void __init sbus_time_init(void) ...@@ -441,9 +441,9 @@ void __init sbus_time_init(void)
intersil_start(iregs); intersil_start(iregs);
xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
wall_to_monotonic.tv_nsec = -xtime.tv_nsec; set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec); printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec);
} }
#endif #endif
...@@ -512,6 +512,9 @@ int do_settimeofday(struct timespec *tv) ...@@ -512,6 +512,9 @@ int do_settimeofday(struct timespec *tv)
static int sbus_do_settimeofday(struct timespec *tv) static int sbus_do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -521,28 +524,15 @@ static int sbus_do_settimeofday(struct timespec *tv) ...@@ -521,28 +524,15 @@ static int sbus_do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* made, and then undo it! * made, and then undo it!
*/ */
tv->tv_nsec -= 1000 * (do_gettimeoffset() + nsec -= 1000 * (do_gettimeoffset() +
(jiffies - wall_jiffies) * (USEC_PER_SEC / HZ)); (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ));
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
}
wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) { set_normalized_timespec(&xtime, sec, nsec);
wall_to_monotonic.tv_nsec -= NSEC_PER_SEC; set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
wall_to_monotonic.tv_sec++;
}
if (wall_to_monotonic.tv_nsec < 0) {
wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
wall_to_monotonic.tv_sec--;
}
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
......
...@@ -703,9 +703,9 @@ static void __init set_system_time(void) ...@@ -703,9 +703,9 @@ static void __init set_system_time(void)
} }
xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
wall_to_monotonic.tv_nsec = -xtime.tv_nsec; set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
if (mregs) { if (mregs) {
tmp = mostek_read(mregs + MOSTEK_CREG); tmp = mostek_read(mregs + MOSTEK_CREG);
...@@ -743,9 +743,9 @@ void __init clock_probe(void) ...@@ -743,9 +743,9 @@ void __init clock_probe(void)
(unsigned int) (long) &unix_tod); (unsigned int) (long) &unix_tod);
prom_feval(obp_gettod); prom_feval(obp_gettod);
xtime.tv_sec = unix_tod; xtime.tv_sec = unix_tod;
wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
wall_to_monotonic.tv_nsec = -xtime.tv_nsec; set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
return; return;
} }
...@@ -1090,6 +1090,9 @@ static __inline__ unsigned long do_gettimeoffset(void) ...@@ -1090,6 +1090,9 @@ static __inline__ unsigned long do_gettimeoffset(void)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
...@@ -1103,28 +1106,15 @@ int do_settimeofday(struct timespec *tv) ...@@ -1103,28 +1106,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* made, and then undo it! * made, and then undo it!
*/ */
tv->tv_nsec -= do_gettimeoffset() * 1000; nsec -= do_gettimeoffset() * 1000;
tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ); nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) { set_normalized_timespec(&xtime, sec, nsec);
wall_to_monotonic.tv_nsec -= NSEC_PER_SEC; set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
wall_to_monotonic.tv_sec++;
}
if (wall_to_monotonic.tv_nsec < 0) {
wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
wall_to_monotonic.tv_sec--;
}
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
......
...@@ -125,33 +125,22 @@ void do_gettimeofday(struct timeval *tv) ...@@ -125,33 +125,22 @@ void do_gettimeofday(struct timeval *tv)
int do_settimeofday(struct timespec *tv) int do_settimeofday(struct timespec *tv)
{ {
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL; return -EINVAL;
write_seqlock_irq(&xtime_lock); write_seqlock_irq(&xtime_lock);
tv->tv_nsec -= do_gettimeoffset() * 1000 + nsec -= do_gettimeoffset() * 1000 +
(jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ); (jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ);
while (tv->tv_nsec < 0) { wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
tv->tv_nsec += NSEC_PER_SEC; wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
tv->tv_sec--;
}
wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
wall_to_monotonic.tv_sec++;
}
if (wall_to_monotonic.tv_nsec < 0) {
wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
wall_to_monotonic.tv_sec--;
}
xtime.tv_sec = tv->tv_sec; set_normalized_timespec(&xtime, sec, nsec);
xtime.tv_nsec = tv->tv_nsec; set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
...@@ -603,8 +592,8 @@ void __init time_init(void) ...@@ -603,8 +592,8 @@ void __init time_init(void)
xtime.tv_sec = get_cmos_time(); xtime.tv_sec = get_cmos_time();
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
wall_to_monotonic.tv_sec = -xtime.tv_sec; set_normalized_timespec(&wall_to_monotonic,
wall_to_monotonic.tv_nsec = -xtime.tv_nsec; -xtime.tv_sec, -xtime.tv_nsec);
if (!hpet_init()) { if (!hpet_init()) {
vxtime_hz = (1000000000000000L + hpet_period / 2) / vxtime_hz = (1000000000000000L + hpet_period / 2) /
......
...@@ -217,6 +217,21 @@ extern void clock_was_set(void); // call when ever the clock is set ...@@ -217,6 +217,21 @@ extern void clock_was_set(void); // call when ever the clock is set
extern int do_posix_clock_monotonic_gettime(struct timespec *tp); extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
extern long do_nanosleep(struct timespec *t); extern long do_nanosleep(struct timespec *t);
extern long do_utimes(char __user * filename, struct timeval * times); extern long do_utimes(char __user * filename, struct timeval * times);
static inline void
set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
{
while (nsec > NSEC_PER_SEC) {
nsec -= NSEC_PER_SEC;
++sec;
}
while (nsec < 0) {
nsec += NSEC_PER_SEC;
--sec;
}
ts->tv_sec = sec;
ts->tv_nsec = nsec;
}
#endif #endif
#define FD_SETSIZE __FD_SETSIZE #define FD_SETSIZE __FD_SETSIZE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment