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)
int
do_settimeofday(struct timespec *tv)
{
time_t wtm_sec, sec = tv->tv_sec;
long wtm_nsec, nsec = tv->tv_nsec;
unsigned long delta_nsec;
long sec, nsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
......@@ -474,31 +475,19 @@ do_settimeofday(struct timespec *tv)
delta_nsec *= 1000;
#endif
sec = tv->tv_sec;
nsec = tv->tv_nsec;
nsec -= delta_nsec;
if (nsec < 0) {
nsec += NSEC_PER_SEC;
sec -= 1;
}
xtime.tv_sec = sec;
xtime.tv_nsec = nsec;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
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_status |= STA_UNSYNC;
time_maxerror = 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);
return 0;
}
......
......@@ -115,6 +115,9 @@ void do_gettimeofday(struct timeval *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)
return -EINVAL;
......@@ -125,28 +128,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
tv->tv_nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - 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--;
}
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_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......
......@@ -104,21 +104,6 @@ static struct time_interpolator itc_interpolator = {
.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
do_settimeofday (struct timespec *tv)
{
......
......@@ -103,6 +103,7 @@ void time_init(void)
time.tm_hour, time.tm_min, time.tm_sec);
xtime.tv_nsec = 0;
}
wall_to_monotonic.tv_sec = -xtime.tv_sec;
mach_sched_init(timer_interrupt);
}
......@@ -140,6 +141,8 @@ void do_gettimeofday(struct timeval *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;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
......@@ -152,16 +155,15 @@ int do_settimeofday(struct timespec *tv)
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
tv->tv_nsec -= 1000 * (mach_gettimeoffset() +
nsec -= 1000 * (mach_gettimeoffset() +
(jiffies - wall_jiffies) * (1000000 / HZ));
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
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);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......
......@@ -131,6 +131,7 @@ void time_init(void)
year += 100;
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_nsec = 0;
wall_to_monotonic.tv_sec = -xtime.tv_sec;
mach_sched_init(timer_interrupt);
}
......@@ -165,6 +166,9 @@ void do_gettimeofday(struct timeval *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)
return -EINVAL;
......@@ -177,15 +181,14 @@ int do_settimeofday(struct timespec *tv)
* would have done, and then undo it!
*/
if (mach_gettimeoffset)
tv->tv_nsec -= (mach_gettimeoffset() * 1000);
nsec -= (mach_gettimeoffset() * 1000);
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
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);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......
......@@ -98,6 +98,9 @@ void do_gettimeofday(struct timeval *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)
return -EINVAL;
......@@ -108,16 +111,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC;
tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
nsec -= do_gettimeoffset() * NSEC_PER_USEC;
nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
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);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......@@ -500,6 +502,9 @@ void __init time_init(void)
xtime.tv_sec = rtc_get_time();
xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
/* choose appropriate gettimeoffset routine */
if (!cpu_has_counter) {
/* no cpu counter - sorry */
......
......@@ -98,6 +98,9 @@ void do_gettimeofday(struct timeval *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)
return -EINVAL;
......@@ -108,16 +111,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC;
tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
nsec -= do_gettimeoffset() * NSEC_PER_USEC;
nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - tsec);
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);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......@@ -499,6 +501,8 @@ void __init time_init(void)
xtime.tv_sec = rtc_get_time();
xtime.tv_nsec = 0;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
/* choose appropriate gettimeoffset routine */
if (!cpu_has_counter) {
......
......@@ -190,6 +190,9 @@ do_gettimeofday (struct timeval *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)
return -EINVAL;
......@@ -202,16 +205,15 @@ do_settimeofday (struct timespec *tv)
* Discover what correction gettimeofday would have
* done, and then undo it!
*/
tv->tv_nsec -= gettimeoffset() * 1000;
tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
nsec -= gettimeoffset() * 1000;
nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
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);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......@@ -243,6 +245,8 @@ void __init time_init(void)
write_seqlock_irq(&xtime_lock);
xtime.tv_sec = tod_data.tod_sec;
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);
} else {
printk(KERN_ERR "Error reading tod clock\n");
......
......@@ -241,6 +241,8 @@ void do_gettimeofday(struct timeval *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;
int tb_delta, new_nsec, new_sec;
......@@ -268,14 +270,14 @@ int do_settimeofday(struct timespec *tv)
*/
tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
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);
while (new_nsec < 0) {
new_sec--;
new_nsec += NSEC_PER_SEC;
}
xtime.tv_nsec = new_nsec;
xtime.tv_sec = new_sec;
new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
set_normalized_timespec(&xtime, new_sec, new_nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
/* 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.
......@@ -347,6 +349,8 @@ void __init time_init(void)
sys_tz.tz_dsttime = 0;
xtime.tv_sec -= time_offset;
}
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
}
#define FEBRUARY 2
......
......@@ -339,9 +339,11 @@ void do_gettimeofday(struct timeval *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 delta_xsec;
long int tb_delta, new_nsec, new_sec;
long int tb_delta;
unsigned long new_xsec;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
......@@ -364,14 +366,13 @@ int do_settimeofday(struct timespec *tv)
tb_delta = tb_ticks_since(tb_last_stamp);
tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
new_sec = tv->tv_sec;
new_nsec = tv->tv_nsec - (tb_delta / tb_ticks_per_usec / 1000);
while (new_nsec < 0) {
new_sec--;
new_nsec += NSEC_PER_SEC;
}
xtime.tv_nsec = new_nsec;
xtime.tv_sec = new_sec;
new_nsec -= tb_delta / tb_ticks_per_usec / 1000;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
set_normalized_timespec(&xtime, new_sec, new_nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
/* 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.
......@@ -484,6 +485,8 @@ void __init time_init(void)
xtime.tv_nsec = 0;
last_rtc_update = xtime.tv_sec;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
write_sequnlock_irqrestore(&xtime_lock, flags);
/* Not exact, but the timer interrupt takes care of this */
......
......@@ -104,6 +104,9 @@ void do_gettimeofday(struct timeval *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)
return -EINVAL;
......@@ -114,15 +117,14 @@ int do_settimeofday(struct timespec *tv)
* Discover what correction gettimeofday
* would have done, and then undo it!
*/
tv->tv_nsec -= do_gettimeoffset() * 1000;
nsec -= do_gettimeoffset() * 1000;
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
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);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......@@ -263,6 +265,8 @@ void __init time_init(void)
set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
(0x3c26700LL*1000000*4096);
tod_to_timeval(set_time_cc, &xtime);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
/* request the 0x1004 external interrupt */
if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
......
......@@ -179,6 +179,9 @@ void do_gettimeofday(struct timeval *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)
return -EINVAL;
......@@ -189,16 +192,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
tv->tv_nsec -= 1000 * (do_gettimeoffset() +
nsec -= 1000 * (do_gettimeoffset() +
(jiffies - wall_jiffies) * (1000000 / HZ));
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
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);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......@@ -418,6 +420,9 @@ void __init time_init(void)
rtc_get_time(&xtime);
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
if (board_timer_setup) {
board_timer_setup(&irq0);
} else {
......
......@@ -408,9 +408,9 @@ void __init sbus_time_init(void)
mon = MSTK_REG_MONTH(mregs);
year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
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);
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;
spin_unlock_irq(&mostek_lock);
#ifdef CONFIG_SUN4
......@@ -441,9 +441,9 @@ void __init sbus_time_init(void)
intersil_start(iregs);
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);
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);
}
#endif
......@@ -512,6 +512,9 @@ int 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)
return -EINVAL;
......@@ -521,28 +524,15 @@ static int sbus_do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
tv->tv_nsec -= 1000 * (do_gettimeoffset() +
nsec -= 1000 * (do_gettimeoffset() +
(jiffies - wall_jiffies) * (USEC_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;
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - 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--;
}
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_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......
......@@ -703,9 +703,9 @@ static void __init set_system_time(void)
}
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);
wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
if (mregs) {
tmp = mostek_read(mregs + MOSTEK_CREG);
......@@ -743,9 +743,9 @@ void __init clock_probe(void)
(unsigned int) (long) &unix_tod);
prom_feval(obp_gettod);
xtime.tv_sec = unix_tod;
wall_to_monotonic.tv_sec = -xtime.tv_sec;
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;
}
......@@ -1090,6 +1090,9 @@ static __inline__ unsigned long do_gettimeoffset(void)
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)
return -EINVAL;
......@@ -1103,28 +1106,15 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
tv->tv_nsec -= do_gettimeoffset() * 1000;
tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
while (tv->tv_nsec < 0) {
tv->tv_nsec += NSEC_PER_SEC;
tv->tv_sec--;
}
nsec -= do_gettimeoffset() * 1000;
nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - 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--;
}
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_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
......
......@@ -125,33 +125,22 @@ void do_gettimeofday(struct timeval *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)
return -EINVAL;
write_seqlock_irq(&xtime_lock);
tv->tv_nsec -= do_gettimeoffset() * 1000 +
nsec -= do_gettimeoffset() * 1000 +
(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;
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--;
}
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
xtime.tv_sec = tv->tv_sec;
xtime.tv_nsec = tv->tv_nsec;
set_normalized_timespec(&xtime, sec, nsec);
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
......@@ -603,8 +592,8 @@ void __init time_init(void)
xtime.tv_sec = get_cmos_time();
xtime.tv_nsec = 0;
wall_to_monotonic.tv_sec = -xtime.tv_sec;
wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
if (!hpet_init()) {
vxtime_hz = (1000000000000000L + hpet_period / 2) /
......
......@@ -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 long do_nanosleep(struct timespec *t);
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
#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