From 61c340166d8c62086b6de00afc7670eea27eb2ab Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 24 Jun 2006 16:05:18 +0000 Subject: [PATCH] [PARISC] Fix do_gettimeofday() hang Apparently gettimeoffset can return small negative values (usually in the 100us range). If xtime.tv_nsec is accidentally less than this, though (a fortunately unlikely event) it triggers the loop forever. I've added a test and correct adjustment for this case. It has a warning printk in there which I'd like to leave for the time being just in case this problem implicates some other part of the kernel. Signed-off-by: James Bottomley Signed-off-by: Kyle McMartin --- arch/parisc/kernel/time.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 594930b..eb35e1c 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -157,8 +157,22 @@ do_gettimeofday (struct timeval *tv) usec += (xtime.tv_nsec / 1000); } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - while (usec >= 1000000) { - usec -= 1000000; + if (unlikely(usec > LONG_MAX)) { + /* This can happen if the gettimeoffset adjustment is + * negative and xtime.tv_nsec is smaller than the + * adjustment */ + printk(KERN_ERR "do_gettimeofday() spurious xtime.tv_nsec of %ld\n", usec); + usec += USEC_PER_SEC; + --sec; + /* This should never happen, it means the negative + * time adjustment was more than a second, so there's + * something seriously wrong */ + BUG_ON(usec > LONG_MAX); + } + + + while (usec >= USEC_PER_SEC) { + usec -= USEC_PER_SEC; ++sec; } -- 2.7.4