|
|
Log in / Subscribe / Register

(4/4) 2.5.59 fast reader/writer lock for gettimeofday

From:  Stephen Hemminger <shemminger@osdl.org>
To:  Linus Torvalds <torvalds@transmeta.com>
Subject:  [PATCH] (4/4) 2.5.59 fast reader/writer lock for gettimeofday
Date:  28 Jan 2003 15:43:19 -0800
Cc:  Andrew Morton <akpm@digeo.com>, Andrea Arcangeli <andrea@suse.de>, Andi Kleen <ak@suse.de>, Linux Kernel Mailing List <linux-kernel@vger.kernel.org>

This is the other architecture support for lockless gettimeofday. 
Applies cleanly, but has not been tested.
It defines frlock and changes locking of xtime_lock from rwlock to
frlock.

diff -urN -X dontdiff linux-2.5.59/arch/alpha/kernel/time.c linux-2.5-frlock/arch/alpha/kernel/time.c
--- linux-2.5.59/arch/alpha/kernel/time.c	2003-01-17 09:42:13.000000000 -0800
+++ linux-2.5-frlock/arch/alpha/kernel/time.c	2003-01-21 13:20:21.000000000 -0800
@@ -51,7 +51,7 @@
 
 u64 jiffies_64;
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern unsigned long wall_jiffies;	/* kernel/timer.c */
 
 static int set_rtc_mmss(unsigned long);
@@ -106,7 +106,7 @@
 		alpha_do_profile(regs->pc);
 #endif
 
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 
 	/*
 	 * Calculate how many ticks have passed since the last update,
@@ -138,7 +138,7 @@
 		state.last_rtc_update = xtime.tv_sec - (tmp ? 600 : 0);
 	}
 
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 void
@@ -410,18 +410,19 @@
 void
 do_gettimeofday(struct timeval *tv)
 {
-	unsigned long sec, usec, lost, flags;
+	unsigned long sec, usec, lost, seq;
 	unsigned long delta_cycles, delta_usec, partial_tick;
 
-	read_lock_irqsave(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	delta_cycles = rpcc() - state.last_time;
-	sec = xtime.tv_sec;
-	usec = (xtime.tv_nsec / 1000);
-	partial_tick = state.partial_tick;
-	lost = jiffies - wall_jiffies;
+		delta_cycles = rpcc() - state.last_time;
+		sec = xtime.tv_sec;
+		usec = (xtime.tv_nsec / 1000);
+		partial_tick = state.partial_tick;
+		lost = jiffies - wall_jiffies;
 
-	read_unlock_irqrestore(&xtime_lock, flags);
+	} while (seq != fr_read_end(&xtime_lock));
 
 #ifdef CONFIG_SMP
 	/* Until and unless we figure out how to get cpu cycle counters
@@ -463,7 +464,7 @@
 	unsigned long delta_usec;
 	long sec, usec;
 	
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 
 	/* The offset that is added into time in do_gettimeofday above
 	   must be subtracted out here to keep a coherent view of the
@@ -494,7 +495,7 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 
diff -urN -X dontdiff linux-2.5.59/arch/arm/kernel/time.c linux-2.5-frlock/arch/arm/kernel/time.c
--- linux-2.5.59/arch/arm/kernel/time.c	2003-01-17 09:42:13.000000000 -0800
+++ linux-2.5-frlock/arch/arm/kernel/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -34,7 +34,7 @@
 
 u64 jiffies_64;
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern unsigned long wall_jiffies;
 
 /* this needs a better home */
@@ -147,19 +147,20 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec, lost;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = gettimeoffset();
-
-	lost = jiffies - wall_jiffies;
-	if (lost)
-		usec += lost * USECS_PER_JIFFY;
-
-	sec = xtime.tv_sec;
-	usec += xtime.tv_nsec / 1000;
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		usec = gettimeoffset();
+
+		lost = jiffies - wall_jiffies;
+		if (lost)
+			usec += lost * USECS_PER_JIFFY;
+
+		sec = xtime.tv_sec;
+		usec += xtime.tv_nsec / 1000;
+	} while (seq != fr_read_end(&xtime_lock));
 
 	/* usec may have gone up a lot: be safe */
 	while (usec >= 1000000) {
@@ -173,7 +174,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	/*
 	 * This is revolting. We need to set "xtime" correctly. However, the
 	 * value in this location is the value at the most recent update of
@@ -194,7 +195,7 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 static struct irqaction timer_irq = {
diff -urN -X dontdiff linux-2.5.59/arch/m68k/kernel/time.c linux-2.5-frlock/arch/m68k/kernel/time.c
--- linux-2.5.59/arch/m68k/kernel/time.c	2003-01-17 09:42:15.000000000 -0800
+++ linux-2.5-frlock/arch/m68k/kernel/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -129,7 +129,7 @@
 	mach_sched_init(timer_interrupt);
 }
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 /*
  * This version of gettimeofday has near microsecond resolution.
@@ -137,17 +137,20 @@
 void do_gettimeofday(struct timeval *tv)
 {
 	extern unsigned long wall_jiffies;
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec, lost;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = mach_gettimeoffset();
-	lost = jiffies - wall_jiffies;
-	if (lost)
-		usec += lost * (1000000/HZ);
-	sec = xtime.tv_sec;
-	usec += xtime.tv_nsec/1000;
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+
+		usec = mach_gettimeoffset();
+		lost = jiffies - wall_jiffies;
+		if (lost)
+			usec += lost * (1000000/HZ);
+		sec = xtime.tv_sec;
+		usec += xtime.tv_nsec/1000;
+	} while (seq != fr_read_end(&xtime_lock));
+
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -162,7 +165,7 @@
 {
 	extern unsigned long wall_jiffies;
 
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	/* This is revolting. We need to set the xtime.tv_nsec
 	 * correctly. However, the value in this location is
 	 * is value at the last tick.
@@ -183,5 +186,5 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
diff -urN -X dontdiff linux-2.5.59/arch/m68knommu/kernel/time.c linux-2.5-frlock/arch/m68knommu/kernel/time.c
--- linux-2.5.59/arch/m68knommu/kernel/time.c	2003-01-17 09:42:15.000000000 -0800
+++ linux-2.5-frlock/arch/m68knommu/kernel/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -126,21 +126,24 @@
 	mach_sched_init(timer_interrupt);
 }
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 /*
  * This version of gettimeofday has near microsecond resolution.
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
-	sec = xtime.tv_sec;
-	usec += (xtime.tv_nsec / 1000);
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+
+		usec = mach_gettimeoffset ? mach_gettimeoffset() : 0;
+		sec = xtime.tv_sec;
+		usec += (xtime.tv_nsec / 1000);
+	} while (seq != fr_read_end(&xtime_lock));
+
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -153,7 +156,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	/* This is revolting. We need to set the xtime.tv_usec
 	 * correctly. However, the value in this location is
 	 * is value at the last tick.
@@ -174,5 +177,5 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
diff -urN -X dontdiff linux-2.5.59/arch/mips/au1000/common/time.c linux-2.5-frlock/arch/mips/au1000/common/time.c
--- linux-2.5.59/arch/mips/au1000/common/time.c	2003-01-17 09:42:15.000000000 -0800
+++ linux-2.5-frlock/arch/mips/au1000/common/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -44,7 +44,7 @@
 
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 
@@ -150,10 +150,10 @@
 	set_cp0_status(ALLINTS);
 
 	/* Read time from the RTC chipset. */
-	write_lock_irqsave (&xtime_lock, flags);
+	fr_write_lock_irqsave (&xtime_lock, flags);
 	xtime.tv_sec = get_mips_time();
 	xtime.tv_usec = 0;
-	write_unlock_irqrestore(&xtime_lock, flags);
+	fr_write_unlock_irqrestore(&xtime_lock, flags);
 }
 
 /* This is for machines which generate the exact clock. */
@@ -229,20 +229,23 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned int flags;
+	unsigned long seq;
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_fast_gettimeoffset();
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+		*tv = xtime;
+		tv->tv_usec += do_fast_gettimeoffset();
+
+		/*
+		 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+		 * is nonzero if the timer bottom half hasnt executed yet.
+		 */
+		if (jiffies - wall_jiffies)
+			tv->tv_usec += USECS_PER_JIFFY;
+
+	} while (seq != fr_read_end(&xtime_lock));
 
-	read_unlock_irqrestore (&xtime_lock, flags);
 
 	if (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
@@ -252,7 +255,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq (&xtime_lock);
+	fr_write_lock_irq (&xtime_lock);
 
 	/* This is revolting. We need to set the xtime.tv_usec correctly.
 	 * However, the value in this location is is value at the last tick.
@@ -272,7 +275,7 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq (&xtime_lock);
+	fr_write_unlock_irq (&xtime_lock);
 }
 
 /*
diff -urN -X dontdiff linux-2.5.59/arch/mips/baget/time.c linux-2.5-frlock/arch/mips/baget/time.c
--- linux-2.5.59/arch/mips/baget/time.c	2003-01-17 09:42:15.000000000 -0800
+++ linux-2.5-frlock/arch/mips/baget/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -23,7 +23,7 @@
 
 #include <asm/baget/baget.h>
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 /* 
  *  To have precision clock, we need to fix available clock frequency
@@ -79,20 +79,21 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	read_unlock_irqrestore (&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		*tv = xtime;
+	} while (seq != fr_read_end(&xtime_lock));
 }
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq (&xtime_lock);
+	fr_write_lock_irq (&xtime_lock);
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq (&xtime_lock);
+	fr_write_unlock_irq (&xtime_lock);
 }
diff -urN -X dontdiff linux-2.5.59/arch/mips/dec/time.c linux-2.5-frlock/arch/mips/dec/time.c
--- linux-2.5.59/arch/mips/dec/time.c	2003-01-17 09:42:15.000000000 -0800
+++ linux-2.5-frlock/arch/mips/dec/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -35,7 +35,7 @@
 extern void (*board_time_init)(struct irqaction *irq);
 
 extern volatile unsigned long wall_jiffies;
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 /*
  * Change this if you have some constant time drift
@@ -210,20 +210,22 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_gettimeoffset();
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		*tv = xtime;
+		tv->tv_usec += do_gettimeoffset();
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+		/*
+		 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+		 * is nonzero if the timer bottom half hasnt executed yet.
+		 */
+		if (jiffies - wall_jiffies)
+			tv->tv_usec += USECS_PER_JIFFY;
+
+	} while (seq != fr_read_end(&xtime_lock));
 
-	read_unlock_irqrestore(&xtime_lock, flags);
 
 	if (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
@@ -233,7 +235,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 
 	/* This is revolting. We need to set the xtime.tv_usec
 	 * correctly. However, the value in this location is
@@ -254,7 +256,7 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 /*
@@ -330,6 +332,7 @@
 timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	volatile unsigned char dummy;
+	unsigned long seq;
 
 	dummy = CMOS_READ(RTC_REG_C);	/* ACK RTC Interrupt */
 
@@ -357,23 +360,27 @@
 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
 	 * called as close as possible to 500 ms before the new second starts.
 	 */
-	read_lock(&xtime_lock);
-	if ((time_status & STA_UNSYNC) == 0
-	    && xtime.tv_sec > last_rtc_update + 660
-	    && xtime.tv_usec >= 500000 - tick / 2
-	    && xtime.tv_usec <= 500000 + tick / 2) {
-		if (set_rtc_mmss(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			/* do it again in 60 s */
-			last_rtc_update = xtime.tv_sec - 600;
-	}
+	do {
+		seq = fr_read_begin(&xtime_lock);
+
+		if ((time_status & STA_UNSYNC) == 0
+		    && xtime.tv_sec > last_rtc_update + 660
+		    && xtime.tv_usec >= 500000 - tick / 2
+		    && xtime.tv_usec <= 500000 + tick / 2) {
+			if (set_rtc_mmss(xtime.tv_sec) == 0)
+				last_rtc_update = xtime.tv_sec;
+			else
+				/* do it again in 60 s */
+				last_rtc_update = xtime.tv_sec - 600;
+		}
+	} while (seq != fr_read_end(&xtime_lock));
+
 	/* As we return to user mode fire off the other CPU schedulers.. this is
 	   basically because we don't yet share IRQ's around. This message is
 	   rigged to be safe on the 386 - basically it's a hack, so don't look
 	   closely for now.. */
 	/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
-	read_unlock(&xtime_lock);
+
 }
 
 static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -470,10 +477,10 @@
 	real_year = CMOS_READ(RTC_DEC_YEAR);
 	year += real_year - 72 + 2000;
 
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 	xtime.tv_usec = 0;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 
 	if (mips_cpu.options & MIPS_CPU_COUNTER) {
 		write_32bit_cp0_register(CP0_COUNT, 0);
diff -urN -X dontdiff linux-2.5.59/arch/mips/ite-boards/generic/time.c linux-2.5-frlock/arch/mips/ite-boards/generic/time.c
--- linux-2.5.59/arch/mips/ite-boards/generic/time.c	2003-01-17 09:42:15.000000000 -0800
+++ linux-2.5-frlock/arch/mips/ite-boards/generic/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -38,7 +38,7 @@
 
 extern void enable_cpu_timer(void);
 extern volatile unsigned long wall_jiffies;
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 unsigned long missed_heart_beats = 0;
 static long last_rtc_update = 0;
@@ -119,6 +119,8 @@
  */
 void mips_timer_interrupt(struct pt_regs *regs)
 {
+	unsigned long seq;
+
 	if (r4k_offset == 0)
 		goto null;
 
@@ -133,18 +135,22 @@
  		 * within 500ms before the * next second starts, 
  		 * thus the following code.
  		 */
-		read_lock(&xtime_lock);
-		if ((time_status & STA_UNSYNC) == 0 
-		    && xtime.tv_sec > last_rtc_update + 660 
-		    && xtime.tv_usec >= 500000 - (tick >> 1) 
-		    && xtime.tv_usec <= 500000 + (tick >> 1))
-			if (set_rtc_mmss(xtime.tv_sec) == 0)
-				last_rtc_update = xtime.tv_sec;
-			else {
-				/* do it again in 60 s */
-	    			last_rtc_update = xtime.tv_sec - 600; 
-			}
-		read_unlock(&xtime_lock);
+		do {
+			seq = fr_read_begin(&xtime_lock);
+
+
+			if ((time_status & STA_UNSYNC) == 0 
+			    && xtime.tv_sec > last_rtc_update + 660 
+			    && xtime.tv_usec >= 500000 - (tick >> 1) 
+			    && xtime.tv_usec <= 500000 + (tick >> 1))
+				if (set_rtc_mmss(xtime.tv_sec) == 0)
+					last_rtc_update = xtime.tv_sec;
+				else {
+					/* do it again in 60 s */
+					last_rtc_update = xtime.tv_sec - 600; 
+				}
+			
+		} while (seq != fr_read_end(&xtime_lock));
 
 		r4k_cur += r4k_offset;
 		ack_r4ktimer(r4k_cur);
@@ -247,10 +253,10 @@
 	enable_cpu_timer();
 
 	/* Read time from the RTC chipset. */
-	write_lock_irqsave (&xtime_lock, flags);
+	fr_write_lock_irqsave (&xtime_lock, flags);
 	xtime.tv_sec = get_mips_time();
 	xtime.tv_usec = 0;
-	write_unlock_irqrestore(&xtime_lock, flags);
+	fr_write_unlock_irqrestore(&xtime_lock, flags);
 }
 
 /* This is for machines which generate the exact clock. */
@@ -332,20 +338,23 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned int flags;
+	unsigned int seq;
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_fast_gettimeoffset();
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+		*tv = xtime;
+		tv->tv_usec += do_fast_gettimeoffset();
+
+		/*
+		 * xtime is atomically updated in timer_bh. 
+		 * jiffies - wall_jiffies
+		 * is nonzero if the timer bottom half hasnt executed yet.
+		 */
+		if (jiffies - wall_jiffies)
+			tv->tv_usec += USECS_PER_JIFFY;
 
-	read_unlock_irqrestore (&xtime_lock, flags);
+	} while (seq != fr_read_end(&xtime_lock));
 
 	if (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
@@ -355,7 +364,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq (&xtime_lock);
+	fr_write_lock_irq (&xtime_lock);
 
 	/* This is revolting. We need to set the xtime.tv_usec correctly.
 	 * However, the value in this location is is value at the last tick.
@@ -375,5 +384,5 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq (&xtime_lock);
+	fr_write_unlock_irq (&xtime_lock);
 }
diff -urN -X dontdiff linux-2.5.59/arch/mips/kernel/sysirix.c linux-2.5-frlock/arch/mips/kernel/sysirix.c
--- linux-2.5.59/arch/mips/kernel/sysirix.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/mips/kernel/sysirix.c	2003-01-24 14:54:11.000000000 -0800
@@ -615,19 +615,19 @@
 	return current->gid;
 }
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 asmlinkage int irix_stime(int value)
 {
 	if (!capable(CAP_SYS_TIME))
 		return -EPERM;
 
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	xtime.tv_sec = value;
 	xtime.tv_usec = 0;
 	time_maxerror = MAXPHASE;
 	time_esterror = MAXPHASE;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 
 	return 0;
 }
diff -urN -X dontdiff linux-2.5.59/arch/mips/kernel/time.c linux-2.5-frlock/arch/mips/kernel/time.c
--- linux-2.5.59/arch/mips/kernel/time.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/mips/kernel/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -37,7 +37,7 @@
 /*
  * forward reference
  */
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern volatile unsigned long wall_jiffies;
 
 /*
@@ -62,20 +62,23 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_gettimeoffset();
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+		*tv = xtime;
+		tv->tv_usec += do_gettimeoffset();
+
+		/*
+		 * xtime is atomically updated in timer_bh. 
+		 * jiffies - wall_jiffies
+		 * is nonzero if the timer bottom half hasnt executed yet.
+		 */
+		if (jiffies - wall_jiffies)
+			tv->tv_usec += USECS_PER_JIFFY;
+	} while (seq != fr_read_end(&xtime_lock));
 
-	read_unlock_irqrestore (&xtime_lock, flags);
 
 	if (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
@@ -85,7 +88,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq (&xtime_lock);
+	fr_write_lock_irq (&xtime_lock);
 
 	/* This is revolting. We need to set the xtime.tv_usec
 	 * correctly. However, the value in this location is
@@ -105,7 +108,7 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq (&xtime_lock);
+	fr_write_unlock_irq (&xtime_lock);
 }
 
 
@@ -291,6 +294,8 @@
  */
 void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long seq;
+
 	if (mips_cpu.options & MIPS_CPU_COUNTER) {
 		unsigned int count;
 
@@ -340,19 +345,21 @@
 	 * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
 	 * called as close as possible to 500 ms before the new second starts.
 	 */
-	read_lock (&xtime_lock);
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
-	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
-		if (rtc_set_time(xtime.tv_sec) == 0) {
-			last_rtc_update = xtime.tv_sec;
-		} else {
-			last_rtc_update = xtime.tv_sec - 600; 
-			/* do it again in 60 s */
+	do {
+		seq = fr_read_begin(&xtime_lock);
+	
+		if ((time_status & STA_UNSYNC) == 0 &&
+		    xtime.tv_sec > last_rtc_update + 660 &&
+		    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+		    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
+			if (rtc_set_time(xtime.tv_sec) == 0) {
+				last_rtc_update = xtime.tv_sec;
+			} else {
+				last_rtc_update = xtime.tv_sec - 600; 
+				/* do it again in 60 s */
+			}
 		}
-	}
-	read_unlock (&xtime_lock);
+	} while (seq != fr_read_end(&xtime_lock));
 
 	/*
 	 * If jiffies has overflowed in this timer_interrupt we must
diff -urN -X dontdiff linux-2.5.59/arch/mips/mips-boards/generic/time.c linux-2.5-frlock/arch/mips/mips-boards/generic/time.c
--- linux-2.5.59/arch/mips/mips-boards/generic/time.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/mips/mips-boards/generic/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -45,7 +45,7 @@
 
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 
@@ -134,6 +134,7 @@
 void mips_timer_interrupt(struct pt_regs *regs)
 {
 	int irq = 7;
+	unsigned long seq;
 
 	if (r4k_offset == 0)
 		goto null;
@@ -149,18 +150,21 @@
  		 * within 500ms before the * next second starts, 
  		 * thus the following code.
  		 */
-		read_lock(&xtime_lock);
-		if ((time_status & STA_UNSYNC) == 0 
-		    && xtime.tv_sec > last_rtc_update + 660 
-		    && xtime.tv_usec >= 500000 - (tick >> 1) 
-		    && xtime.tv_usec <= 500000 + (tick >> 1))
-			if (set_rtc_mmss(xtime.tv_sec) == 0)
-				last_rtc_update = xtime.tv_sec;
-			else
-				/* do it again in 60 s */
-	    			last_rtc_update = xtime.tv_sec - 600; 
-		read_unlock(&xtime_lock);
 
+		do {
+			seq = fr_read_begin(&xtime_lock);
+
+			if ((time_status & STA_UNSYNC) == 0 
+			    && xtime.tv_sec > last_rtc_update + 660 
+			    && xtime.tv_usec >= 500000 - (tick >> 1) 
+			    && xtime.tv_usec <= 500000 + (tick >> 1))
+				if (set_rtc_mmss(xtime.tv_sec) == 0)
+					last_rtc_update = xtime.tv_sec;
+				else
+					/* do it again in 60 s */
+					last_rtc_update = xtime.tv_sec - 600; 
+		} while (seq != fr_read_end(&xtime_lock));
+		
 		if ((timer_tick_count++ % HZ) == 0) {
 		    mips_display_message(&display_string[display_count++]);
 		    if (display_count == MAX_DISPLAY_COUNT)
@@ -267,10 +271,10 @@
 	change_cp0_status(ST0_IM, ALLINTS);
 
 	/* Read time from the RTC chipset. */
-	write_lock_irqsave (&xtime_lock, flags);
+	fr_write_lock_irqsave (&xtime_lock, flags);
 	xtime.tv_sec = get_mips_time();
 	xtime.tv_usec = 0;
-	write_unlock_irqrestore(&xtime_lock, flags);
+	fr_write_unlock_irqrestore(&xtime_lock, flags);
 }
 
 /* This is for machines which generate the exact clock. */
@@ -363,20 +367,23 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned int flags;
+	unsigned long seq;
+
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_fast_gettimeoffset();
+		*tv = xtime;
+		tv->tv_usec += do_fast_gettimeoffset();
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+		/*
+		 * xtime is atomically updated in timer_bh. 
+		 * jiffies - wall_jiffies
+		 * is nonzero if the timer bottom half hasnt executed yet.
+		 */
+		if (jiffies - wall_jiffies)
+			tv->tv_usec += USECS_PER_JIFFY;
 
-	read_unlock_irqrestore (&xtime_lock, flags);
+	} while (seq != fr_read_end(&xtime_lock));
 
 	if (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
@@ -386,7 +393,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq (&xtime_lock);
+	fr_write_lock_irq (&xtime_lock);
 
 	/* This is revolting. We need to set the xtime.tv_usec correctly.
 	 * However, the value in this location is is value at the last tick.
@@ -406,5 +413,5 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq (&xtime_lock);
+	fr_write_unlock_irq (&xtime_lock);
 }
diff -urN -X dontdiff linux-2.5.59/arch/mips/philips/nino/time.c linux-2.5-frlock/arch/mips/philips/nino/time.c
--- linux-2.5.59/arch/mips/philips/nino/time.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/mips/philips/nino/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -24,7 +24,7 @@
 #include <asm/tx3912.h>
 
 extern volatile unsigned long wall_jiffies;
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 static struct timeval xbase;
 
@@ -61,30 +61,31 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-    unsigned long flags;
+    unsigned long seq;
     unsigned long high, low;
 
-    read_lock_irqsave(&xtime_lock, flags);
-    // 40 bit RTC, driven by 32khz source:
-    // +-----------+-----------------------------------------+
-    // | HHHH.HHHH | LLLL.LLLL.LLLL.LLLL.LMMM.MMMM.MMMM.MMMM |
-    // +-----------+-----------------------------------------+
-    readRTC(&high,&low);
-    tv->tv_sec  = (high << 17) | (low >> 15);
-    tv->tv_usec = (low % 32768) * 1953 / 64;
-    tv->tv_sec += xbase.tv_sec;
-    tv->tv_usec += xbase.tv_usec;
+    do {
+	    seq = fr_read_begin(&xtime_lock);
 
-    tv->tv_usec += do_gettimeoffset();
+	    // 40 bit RTC, driven by 32khz source:
+	    // +-----------+-----------------------------------------+
+	    // | HHHH.HHHH | LLLL.LLLL.LLLL.LLLL.LMMM.MMMM.MMMM.MMMM |
+	    // +-----------+-----------------------------------------+
+	    readRTC(&high,&low);
+	    tv->tv_sec  = (high << 17) | (low >> 15);
+	    tv->tv_usec = (low % 32768) * 1953 / 64;
+	    tv->tv_sec += xbase.tv_sec;
+	    tv->tv_usec += xbase.tv_usec;
 
-    /*
-     * xtime is atomically updated in timer_bh. lost_ticks is
-     * nonzero if the timer bottom half hasnt executed yet.
-     */
-    if (jiffies - wall_jiffies)
-	tv->tv_usec += USECS_PER_JIFFY;
+	    tv->tv_usec += do_gettimeoffset();
 
-    read_unlock_irqrestore(&xtime_lock, flags);
+	    /*
+	     * xtime is atomically updated in timer_bh. lost_ticks is
+	     * nonzero if the timer bottom half hasnt executed yet.
+	     */
+	    if (jiffies - wall_jiffies)
+		    tv->tv_usec += USECS_PER_JIFFY;
+    } while (seq != fr_read_end(&xtime_lock));
 
     if (tv->tv_usec >= 1000000) {
 	tv->tv_usec -= 1000000;
@@ -94,7 +95,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-    write_lock_irq(&xtime_lock);
+    fr_write_lock_irq(&xtime_lock);
     /* This is revolting. We need to set the xtime.tv_usec
      * correctly. However, the value in this location is
      * is value at the last tick.
@@ -118,7 +119,7 @@
     time_state = TIME_BAD;
     time_maxerror = MAXPHASE;
     time_esterror = MAXPHASE;
-    write_unlock_irq(&xtime_lock);
+    fr_write_unlock_irq(&xtime_lock);
 }
 
 static int set_rtc_mmss(unsigned long nowtime)
diff -urN -X dontdiff linux-2.5.59/arch/mips64/mips-boards/generic/time.c linux-2.5-frlock/arch/mips64/mips-boards/generic/time.c
--- linux-2.5.59/arch/mips64/mips-boards/generic/time.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/mips64/mips-boards/generic/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -44,7 +44,7 @@
 
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 
@@ -133,6 +133,7 @@
 void mips_timer_interrupt(struct pt_regs *regs)
 {
 	int irq = 7;
+	unsigned long seq;
 
 	if (r4k_offset == 0)
 		goto null;
@@ -148,17 +149,20 @@
  		 * within 500ms before the * next second starts, 
  		 * thus the following code.
  		 */
-		read_lock(&xtime_lock);
-		if ((time_status & STA_UNSYNC) == 0 
-		    && xtime.tv_sec > last_rtc_update + 660 
-		    && xtime.tv_usec >= 500000 - (tick >> 1) 
-		    && xtime.tv_usec <= 500000 + (tick >> 1))
-			if (set_rtc_mmss(xtime.tv_sec) == 0)
-				last_rtc_update = xtime.tv_sec;
-			else
-				/* do it again in 60 s */
-	    			last_rtc_update = xtime.tv_sec - 600; 
-		read_unlock(&xtime_lock);
+		do {
+			seq = fr_read_begin(&xtime_lock);
+			
+			if ((time_status & STA_UNSYNC) == 0 
+			    && xtime.tv_sec > last_rtc_update + 660 
+			    && xtime.tv_usec >= 500000 - (tick >> 1) 
+			    && xtime.tv_usec <= 500000 + (tick >> 1))
+				if (set_rtc_mmss(xtime.tv_sec) == 0)
+					last_rtc_update = xtime.tv_sec;
+				else
+					/* do it again in 60 s */
+					last_rtc_update = xtime.tv_sec - 600; 
+		} while (seq != fr_read_end(&xtime_lock));
+
 
 		if ((timer_tick_count++ % HZ) == 0) {
 		    mips_display_message(&display_string[display_count++]);
@@ -266,10 +270,10 @@
 	set_cp0_status(ST0_IM, ALLINTS);
 
 	/* Read time from the RTC chipset. */
-	write_lock_irqsave (&xtime_lock, flags);
+	fr_write_lock_irqsave (&xtime_lock, flags);
 	xtime.tv_sec = get_mips_time();
 	xtime.tv_usec = 0;
-	write_unlock_irqrestore(&xtime_lock, flags);
+	fr_write_unlock_irqrestore(&xtime_lock, flags);
 }
 
 /* This is for machines which generate the exact clock. */
@@ -352,20 +356,24 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned int flags;
+	unsigned long seq;
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_fast_gettimeoffset();
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+		*tv = xtime;
+		tv->tv_usec += do_fast_gettimeoffset();
+
+		/*
+		 * xtime is atomically updated in timer_bh. 
+		 * jiffies - wall_jiffies
+		 * is nonzero if the timer bottom half hasnt executed yet.
+		 */
+		if (jiffies - wall_jiffies)
+			tv->tv_usec += USECS_PER_JIFFY;
+
+	} while (seq != fr_read_end(&xtime_lock));
 
-	read_unlock_irqrestore (&xtime_lock, flags);
 
 	if (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
@@ -375,7 +383,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq (&xtime_lock);
+	fr_write_lock_irq (&xtime_lock);
 
 	/* This is revolting. We need to set the xtime.tv_usec correctly.
 	 * However, the value in this location is is value at the last tick.
@@ -395,5 +403,5 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq (&xtime_lock);
+	fr_write_unlock_irq (&xtime_lock);
 }
diff -urN -X dontdiff linux-2.5.59/arch/mips64/sgi-ip22/ip22-timer.c linux-2.5-frlock/arch/mips64/sgi-ip22/ip22-timer.c
--- linux-2.5.59/arch/mips64/sgi-ip22/ip22-timer.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/mips64/sgi-ip22/ip22-timer.c	2003-01-24 14:54:11.000000000 -0800
@@ -32,7 +32,7 @@
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 static inline void ack_r4ktimer(unsigned long newval)
 {
@@ -86,7 +86,7 @@
 	unsigned long count;
 	int irq = 7;
 
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 	/* Ack timer and compute new compare. */
 	count = read_32bit_cp0_register(CP0_COUNT);
 	/* This has races.  */
@@ -116,7 +116,7 @@
 			/* do it again in 60s  */
 			last_rtc_update = xtime.tv_sec - 600;
 	}
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 static unsigned long dosample(volatile unsigned char *tcwp,
@@ -224,10 +224,10 @@
 	set_cp0_status(ST0_IM, ALLINTS);
 	sti();
 
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	xtime.tv_sec = get_indy_time();		/* Read time from RTC. */
 	xtime.tv_usec = 0;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 void indy_8254timer_irq(void)
@@ -243,20 +243,21 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	*tv = xtime;
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		*tv = xtime;
+	} while (seq != fr_read_end(&xtime_lock));
 }
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
diff -urN -X dontdiff linux-2.5.59/arch/mips64/sgi-ip27/ip27-timer.c linux-2.5-frlock/arch/mips64/sgi-ip27/ip27-timer.c
--- linux-2.5.59/arch/mips64/sgi-ip27/ip27-timer.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/mips64/sgi-ip27/ip27-timer.c	2003-01-24 14:54:11.000000000 -0800
@@ -40,7 +40,7 @@
 static unsigned long ct_cur[NR_CPUS];	/* What counter should be at next timer irq */
 static long last_rtc_update;		/* Last time the rtc clock got updated */
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern volatile unsigned long wall_jiffies;
 
 
@@ -94,7 +94,7 @@
 	int cpuA = ((cputoslice(cpu)) == 0);
 	int irq = 7;				/* XXX Assign number */
 
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 
 again:
 	LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0);	/* Ack  */
@@ -145,7 +145,7 @@
 		}
         }
 
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 
 	if (softirq_pending(cpu))
 		do_softirq();
@@ -160,19 +160,21 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
 	unsigned long usec, sec;
+	unsigned long seq;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = do_gettimeoffset();
-	{
-		unsigned long lost = jiffies - wall_jiffies;
-		if (lost)
-			usec += lost * (1000000 / HZ);
-	}
-	sec = xtime.tv_sec;
-	usec += xtime.tv_usec;
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+
+		usec = do_gettimeoffset();
+		{
+			unsigned long lost = jiffies - wall_jiffies;
+			if (lost)
+				usec += lost * (1000000 / HZ);
+		}
+		sec = xtime.tv_sec;
+		usec += xtime.tv_usec;
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -185,7 +187,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	tv->tv_usec -= do_gettimeoffset();
 	tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
 
@@ -199,7 +201,7 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 /* Includes for ioc3_init().  */
diff -urN -X dontdiff linux-2.5.59/arch/parisc/kernel/sys_parisc32.c linux-2.5-frlock/arch/parisc/kernel/sys_parisc32.c
--- linux-2.5.59/arch/parisc/kernel/sys_parisc32.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/parisc/kernel/sys_parisc32.c	2003-01-24 14:54:11.000000000 -0800
@@ -2428,22 +2428,25 @@
 asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
 {
 	struct sysinfo val;
+	unsigned long seq;
 	int err;
-	extern rwlock_t xtime_lock;
+	extern frlock_t xtime_lock;
 
 	/* We don't need a memset here because we copy the
 	 * struct to userspace once element at a time.
 	 */
 
-	read_lock_irq(&xtime_lock);
-	val.uptime = jiffies / HZ;
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
-	val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
-	val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
+		val.uptime = jiffies / HZ;
+		
+		val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
+		val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
+		val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
 
-	val.procs = nr_threads;
-	read_unlock_irq(&xtime_lock);
+		val.procs = nr_threads;
+	} while (seq != fr_read_end(&xtime_lock));
 
 	si_meminfo(&val);
 	si_swapinfo(&val);
diff -urN -X dontdiff linux-2.5.59/arch/parisc/kernel/time.c linux-2.5-frlock/arch/parisc/kernel/time.c
--- linux-2.5.59/arch/parisc/kernel/time.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/parisc/kernel/time.c	2003-01-24 14:54:11.000000000 -0800
@@ -36,7 +36,7 @@
 
 /* xtime and wall_jiffies keep wall-clock time */
 extern unsigned long wall_jiffies;
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 static long clocktick;	/* timer cycles per tick */
 static long halftick;
@@ -115,9 +115,9 @@
 		smp_do_timer(regs);
 #endif
 		if (cpu == 0) {
-			write_lock(&xtime_lock);
+			fr_write_lock(&xtime_lock);
 			do_timer(regs);
-			write_unlock(&xtime_lock);
+			fr_write_unlock(&xtime_lock);
 		}
 	}
     
@@ -172,16 +172,18 @@
 void
 do_gettimeofday (struct timeval *tv)
 {
-	unsigned long flags, usec, sec;
+	unsigned long seq, usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	{
-		usec = gettimeoffset();
+	do {
+		seq = fr_read_begin(&xtime_lock);
+
+		{
+			usec = gettimeoffset();
 	
-		sec = xtime.tv_sec;
-		usec += (xtime.tv_nsec / 1000);
-	}
-	read_unlock_irqrestore(&xtime_lock, flags);
+			sec = xtime.tv_sec;
+			usec += (xtime.tv_nsec / 1000);
+		}
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -195,7 +197,7 @@
 void
 do_settimeofday (struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	{
 		/*
 		 * This is revolting. We need to set "xtime"
@@ -219,7 +221,7 @@
 		time_maxerror = NTP_PHASE_LIMIT;
 		time_esterror = NTP_PHASE_LIMIT;
 	}
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 
@@ -241,10 +243,10 @@
 	mtctl(next_tick, 16);
 
 	if(pdc_tod_read(&tod_data) == 0) {
-		write_lock_irq(&xtime_lock);
+		fr_write_lock_irq(&xtime_lock);
 		xtime.tv_sec = tod_data.tod_sec;
 		xtime.tv_nsec = tod_data.tod_usec * 1000;
-		write_unlock_irq(&xtime_lock);
+		fr_write_unlock_irq(&xtime_lock);
 	} else {
 		printk(KERN_ERR "Error reading tod clock\n");
 	        xtime.tv_sec = 0;
diff -urN -X dontdiff linux-2.5.59/arch/ppc/kernel/time.c linux-2.5-frlock/arch/ppc/kernel/time.c
--- linux-2.5.59/arch/ppc/kernel/time.c	2003-01-17 09:42:16.000000000 -0800
+++ linux-2.5-frlock/arch/ppc/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -76,7 +76,7 @@
 
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 /* The decrementer counts down by 128 every 128ns on a 601. */
 #define DECREMENTER_COUNT_601	(1000000000 / HZ)
@@ -161,7 +161,7 @@
 			continue;
 
 		/* We are in an interrupt, no need to save/restore flags */
-		write_lock(&xtime_lock);
+		fr_write_lock(&xtime_lock);
 		tb_last_stamp = jiffy_stamp;
 		do_timer(regs);
 
@@ -191,7 +191,7 @@
 				/* Try again one minute later */
 				last_rtc_update += 60;
 		}
-		write_unlock(&xtime_lock);
+		fr_write_unlock(&xtime_lock);
 	}
 	if ( !disarm_decr[smp_processor_id()] )
 		set_dec(next_dec);
@@ -212,22 +212,23 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned delta, lost_ticks, usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	sec = xtime.tv_sec;
-	usec = (xtime.tv_nsec / 1000);
-	delta = tb_ticks_since(tb_last_stamp);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		sec = xtime.tv_sec;
+		usec = (xtime.tv_nsec / 1000);
+		delta = tb_ticks_since(tb_last_stamp);
 #ifdef CONFIG_SMP
-	/* As long as timebases are not in sync, gettimeofday can only
-	 * have jiffy resolution on SMP.
-	 */
-	if (!smp_tb_synchronized)
-		delta = 0;
+		/* As long as timebases are not in sync, gettimeofday can only
+		 * have jiffy resolution on SMP.
+		 */
+		if (!smp_tb_synchronized)
+			delta = 0;
 #endif /* CONFIG_SMP */
-	lost_ticks = jiffies - wall_jiffies;
-	read_unlock_irqrestore(&xtime_lock, flags);
+		lost_ticks = jiffies - wall_jiffies;
+	} while (seq != fr_read_end(&xtime_lock));
 
 	usec += mulhwu(tb_to_us, tb_ticks_per_jiffy * lost_ticks + delta);
 	while (usec >= 1000000) {
@@ -243,7 +244,7 @@
 	unsigned long flags;
 	int tb_delta, new_usec, new_sec;
 
-	write_lock_irqsave(&xtime_lock, flags);
+	fr_write_lock_irqsave(&xtime_lock, flags);
 	/* Updating the RTC is not the job of this code. If the time is
 	 * stepped under NTP, the RTC will be update after STA_UNSYNC
 	 * is cleared. Tool like clock/hwclock either copy the RTC
@@ -283,7 +284,7 @@
 	time_state = TIME_ERROR;        /* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irqrestore(&xtime_lock, flags);
+	fr_write_unlock_irqrestore(&xtime_lock, flags);
 }
 
 /* This function is only called on the boot processor */
diff -urN -X dontdiff linux-2.5.59/arch/ppc/platforms/pmac_time.c linux-2.5-frlock/arch/ppc/platforms/pmac_time.c
--- linux-2.5.59/arch/ppc/platforms/pmac_time.c	2003-01-17 09:42:17.000000000 -0800
+++ linux-2.5-frlock/arch/ppc/platforms/pmac_time.c	2003-01-24 14:54:12.000000000 -0800
@@ -29,7 +29,7 @@
 #include <asm/time.h>
 #include <asm/nvram.h>
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 /* Apparently the RTC stores seconds since 1 Jan 1904 */
 #define RTC_OFFSET	2082844800
@@ -218,16 +218,17 @@
 
 	switch (when) {
 	case PBOOK_SLEEP_NOW:
-		read_lock_irqsave(&xtime_lock, flags);
-		time_diff = xtime.tv_sec - pmac_get_rtc_time();
-		read_unlock_irqrestore(&xtime_lock, flags);
+		do {
+			flags = fr_read_begin(&xtime_lock);
+			time_diff = xtime.tv_sec - pmac_get_rtc_time();
+		} while (seq != fr_read_end(&xtime_lock));
 		break;
 	case PBOOK_WAKE:
-		write_lock_irqsave(&xtime_lock, flags);
+		fr_write_lock_irqsave(&xtime_lock, flags);
 		xtime.tv_sec = pmac_get_rtc_time() + time_diff;
 		xtime.tv_nsec = 0;
 		last_rtc_update = xtime.tv_sec;
-		write_unlock_irqrestore(&xtime_lock, flags);
+		fr_write_unlock_irqrestore(&xtime_lock, flags);
 		break;
 	}
 	return PBOOK_SLEEP_OK;
diff -urN -X dontdiff linux-2.5.59/arch/ppc64/kernel/time.c linux-2.5-frlock/arch/ppc64/kernel/time.c
--- linux-2.5.59/arch/ppc64/kernel/time.c	2003-01-17 09:42:23.000000000 -0800
+++ linux-2.5-frlock/arch/ppc64/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -69,7 +69,7 @@
 
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern int piranha_simulator;
 #ifdef CONFIG_PPC_ISERIES
 unsigned long iSeries_recal_titan = 0;
@@ -284,12 +284,12 @@
 		smp_local_timer_interrupt(regs);
 #endif
 		if (cpu == boot_cpuid) {
-			write_lock(&xtime_lock);
+			fr_write_lock(&xtime_lock);
 			tb_last_stamp = lpaca->next_jiffy_update_tb;
 			do_timer(regs);
 			timer_sync_xtime( cur_tb );
 			timer_check_rtc();
-			write_unlock(&xtime_lock);
+			fr_write_unlock(&xtime_lock);
 			if ( adjusting_time && (time_adjust == 0) )
 				ppc_adjtimex();
 		}
@@ -348,7 +348,7 @@
 	long int tb_delta, new_usec, new_sec;
 	unsigned long new_xsec;
 
-	write_lock_irqsave(&xtime_lock, flags);
+	fr_write_lock_irqsave(&xtime_lock, flags);
 	/* Updating the RTC is not the job of this code. If the time is
 	 * stepped under NTP, the RTC will be update after STA_UNSYNC
 	 * is cleared. Tool like clock/hwclock either copy the RTC
@@ -399,7 +399,7 @@
 		do_gtod.tb_orig_stamp = tb_last_stamp;
 	}
 
-	write_unlock_irqrestore(&xtime_lock, flags);
+	fr_write_unlock_irqrestore(&xtime_lock, flags);
 }
 
 /*
@@ -465,7 +465,7 @@
 #endif
 		ppc_md.get_boot_time(&tm);
 
-	write_lock_irqsave(&xtime_lock, flags);
+	fr_write_lock_irqsave(&xtime_lock, flags);
 	xtime.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
 			      tm.tm_hour, tm.tm_min, tm.tm_sec);
 	tb_last_stamp = get_tb();
@@ -484,7 +484,7 @@
 
 	xtime.tv_nsec = 0;
 	last_rtc_update = xtime.tv_sec;
-	write_unlock_irqrestore(&xtime_lock, flags);
+	fr_write_unlock_irqrestore(&xtime_lock, flags);
 
 	/* Not exact, but the timer interrupt takes care of this */
 	set_dec(tb_ticks_per_jiffy);
@@ -587,7 +587,7 @@
 	new_tb_to_xs = divres.result_low;
 	new_xsec = mulhdu( tb_ticks, new_tb_to_xs );
 
-	write_lock_irqsave( &xtime_lock, flags );
+	fr_write_lock_irqsave( &xtime_lock, flags );
 	old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs );
 	new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
 
@@ -609,7 +609,7 @@
 	do_gtod.varp = temp_varp;
 	do_gtod.var_idx = temp_idx;
 
-	write_unlock_irqrestore( &xtime_lock, flags );
+	fr_write_unlock_irqrestore( &xtime_lock, flags );
 
 }
 
diff -urN -X dontdiff linux-2.5.59/arch/s390/kernel/time.c linux-2.5-frlock/arch/s390/kernel/time.c
--- linux-2.5.59/arch/s390/kernel/time.c	2003-01-17 09:42:23.000000000 -0800
+++ linux-2.5-frlock/arch/s390/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -52,7 +52,7 @@
 static uint64_t xtime_cc;
 static uint64_t init_timer_cc;
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern unsigned long wall_jiffies;
 
 void tod_to_timeval(__u64 todval, struct timespec *xtime)
@@ -82,13 +82,15 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	sec = xtime.tv_sec;
-	usec = xtime.tv_nsec / 1000 + do_gettimeoffset();
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+
+		sec = xtime.tv_sec;
+		usec = xtime.tv_nsec / 1000 + do_gettimeoffset();
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -102,7 +104,7 @@
 void do_settimeofday(struct timeval *tv)
 {
 
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	/* This is revolting. We need to set the xtime.tv_nsec
 	 * correctly. However, the value in this location is
 	 * is value at the last tick.
@@ -122,7 +124,7 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 static inline __u32 div64_32(__u64 dividend, __u32 divisor)
@@ -166,7 +168,7 @@
 	 * Do not rely on the boot cpu to do the calls to do_timer.
 	 * Spread it over all cpus instead.
 	 */
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 	if (S390_lowcore.jiffy_timer > xtime_cc) {
 		__u32 xticks;
 
@@ -181,7 +183,7 @@
 		while (xticks--)
 			do_timer(regs);
 	}
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 	while (ticks--)
 		update_process_times(user_mode(regs));
 #else
diff -urN -X dontdiff linux-2.5.59/arch/s390x/kernel/time.c linux-2.5-frlock/arch/s390x/kernel/time.c
--- linux-2.5.59/arch/s390x/kernel/time.c	2003-01-17 09:42:23.000000000 -0800
+++ linux-2.5-frlock/arch/s390x/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -51,7 +51,7 @@
 static uint64_t xtime_cc;
 static uint64_t init_timer_cc;
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern unsigned long wall_jiffies;
 
 void tod_to_timeval(__u64 todval, struct timespec *xtime)
@@ -77,13 +77,14 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	sec = xtime.tv_sec;
-	usec = xtime.tv_nsec + do_gettimeoffset();
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		sec = xtime.tv_sec;
+		usec = xtime.tv_nsec + do_gettimeoffset();
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -97,7 +98,7 @@
 void do_settimeofday(struct timeval *tv)
 {
 
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	/* This is revolting. We need to set the xtime.tv_usec
 	 * correctly. However, the value in this location is
 	 * is value at the last tick.
@@ -117,7 +118,7 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 /*
@@ -152,7 +153,7 @@
 	 * Do not rely on the boot cpu to do the calls to do_timer.
 	 * Spread it over all cpus instead.
 	 */
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 	if (S390_lowcore.jiffy_timer > xtime_cc) {
 		__u32 xticks;
 
@@ -167,7 +168,7 @@
 		while (xticks--)
 			do_timer(regs);
 	}
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 	while (ticks--)
 		update_process_times(user_mode(regs));
 #else
diff -urN -X dontdiff linux-2.5.59/arch/sh/kernel/time.c linux-2.5-frlock/arch/sh/kernel/time.c
--- linux-2.5.59/arch/sh/kernel/time.c	2003-01-17 09:42:23.000000000 -0800
+++ linux-2.5-frlock/arch/sh/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -72,7 +72,7 @@
 
 u64 jiffies_64;
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 extern unsigned long wall_jiffies;
 #define TICK_SIZE tick
 
@@ -127,19 +127,20 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = do_gettimeoffset();
-	{
-		unsigned long lost = jiffies - wall_jiffies;
-		if (lost)
-			usec += lost * (1000000 / HZ);
-	}
-	sec = xtime.tv_sec;
-	usec += xtime.tv_usec;
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		usec = do_gettimeoffset();
+		{
+			unsigned long lost = jiffies - wall_jiffies;
+			if (lost)
+				usec += lost * (1000000 / HZ);
+		}
+		sec = xtime.tv_sec;
+		usec += xtime.tv_usec;
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -152,7 +153,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	/*
 	 * This is revolting. We need to set "xtime" correctly. However, the
 	 * value in this location is the value at the most recent update of
@@ -172,7 +173,7 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 /* last time the RTC clock got updated */
@@ -231,9 +232,9 @@
 	 * the irq version of write_lock because as just said we have irq
 	 * locally disabled. -arca
 	 */
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 	do_timer_interrupt(irq, NULL, regs);
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 static unsigned int __init get_timer_frequency(void)
diff -urN -X dontdiff linux-2.5.59/arch/sparc/kernel/pcic.c linux-2.5-frlock/arch/sparc/kernel/pcic.c
--- linux-2.5.59/arch/sparc/kernel/pcic.c	2003-01-17 09:42:24.000000000 -0800
+++ linux-2.5-frlock/arch/sparc/kernel/pcic.c	2003-01-24 14:54:12.000000000 -0800
@@ -34,7 +34,7 @@
 #include <asm/timer.h>
 #include <asm/uaccess.h>
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 #ifndef CONFIG_PCI
 
@@ -739,10 +739,10 @@
 
 static void pcic_timer_handler (int irq, void *h, struct pt_regs *regs)
 {
-	write_lock(&xtime_lock);	/* Dummy, to show that we remember */
+	fr_write_lock(&xtime_lock);	/* Dummy, to show that we remember */
 	pcic_clear_clock_irq();
 	do_timer(regs);
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 #define USECS_PER_JIFFY  10000  /* We have 100HZ "standard" timer for sparc */
@@ -794,19 +794,20 @@
 
 static void pci_do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = do_gettimeoffset();
-	{
-		unsigned long lost = jiffies - wall_jiffies;
-		if (lost)
-			usec += lost * (1000000 / HZ);
-	}
-	sec = xtime.tv_sec;
-	usec += (xtime.tv_nsec / 1000);
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		usec = do_gettimeoffset();
+		{
+			unsigned long lost = jiffies - wall_jiffies;
+			if (lost)
+				usec += lost * (1000000 / HZ);
+		}
+		sec = xtime.tv_sec;
+		usec += (xtime.tv_nsec / 1000);
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
diff -urN -X dontdiff linux-2.5.59/arch/sparc/kernel/time.c linux-2.5-frlock/arch/sparc/kernel/time.c
--- linux-2.5.59/arch/sparc/kernel/time.c	2003-01-17 09:42:24.000000000 -0800
+++ linux-2.5-frlock/arch/sparc/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -42,7 +42,7 @@
 #include <asm/page.h>
 #include <asm/pcic.h>
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 extern unsigned long wall_jiffies;
 
@@ -131,7 +131,7 @@
 #endif
 
 	/* Protect counter clear so that do_gettimeoffset works */
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 #ifdef CONFIG_SUN4
 	if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) ||
 	   (idprom->id_machtype == (SM_SUN4 | SM_4_110))) {
@@ -155,7 +155,7 @@
 	  else
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 	}
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
@@ -469,19 +469,20 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = do_gettimeoffset();
-	{
-		unsigned long lost = jiffies - wall_jiffies;
-		if (lost)
-			usec += lost * (1000000 / HZ);
-	}
-	sec = xtime.tv_sec;
-	usec += (xtime.tv_nsec / 1000);
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		usec = do_gettimeoffset();
+		{
+			unsigned long lost = jiffies - wall_jiffies;
+			if (lost)
+				usec += lost * (1000000 / HZ);
+		}
+		sec = xtime.tv_sec;
+		usec += (xtime.tv_nsec / 1000);
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -494,9 +495,9 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	bus_do_settimeofday(tv);
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 static void sbus_do_settimeofday(struct timeval *tv)
diff -urN -X dontdiff linux-2.5.59/arch/sparc64/kernel/time.c linux-2.5-frlock/arch/sparc64/kernel/time.c
--- linux-2.5.59/arch/sparc64/kernel/time.c	2003-01-17 09:42:24.000000000 -0800
+++ linux-2.5-frlock/arch/sparc64/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -37,7 +37,7 @@
 #include <asm/isa.h>
 #include <asm/starfire.h>
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -134,7 +134,7 @@
 {
 	unsigned long ticks, pstate;
 
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 
 	do {
 #ifndef CONFIG_SMP
@@ -196,13 +196,13 @@
 
 	timer_check_rtc();
 
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 #ifdef CONFIG_SMP
 void timer_tick_interrupt(struct pt_regs *regs)
 {
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 
 	do_timer(regs);
 
@@ -225,7 +225,7 @@
 
 	timer_check_rtc();
 
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 #endif
 
@@ -665,7 +665,7 @@
 	if (this_is_starfire)
 		return;
 
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	/*
 	 * This is revolting. We need to set "xtime" correctly. However, the
 	 * value in this location is the value at the most recent update of
@@ -686,7 +686,7 @@
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 /* Ok, my cute asm atomicity trick doesn't work anymore.
@@ -695,19 +695,20 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long seq;
 	unsigned long usec, sec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	usec = do_gettimeoffset();
-	{
-		unsigned long lost = jiffies - wall_jiffies;
-		if (lost)
-			usec += lost * (1000000 / HZ);
-	}
-	sec = xtime.tv_sec;
-	usec += (xtime.tv_nsec / 1000);
-	read_unlock_irqrestore(&xtime_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+		usec = do_gettimeoffset();
+		{
+			unsigned long lost = jiffies - wall_jiffies;
+			if (lost)
+				usec += lost * (1000000 / HZ);
+		}
+		sec = xtime.tv_sec;
+		usec += (xtime.tv_nsec / 1000);
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
diff -urN -X dontdiff linux-2.5.59/arch/um/kernel/time_kern.c linux-2.5-frlock/arch/um/kernel/time_kern.c
--- linux-2.5.59/arch/um/kernel/time_kern.c	2003-01-17 09:42:24.000000000 -0800
+++ linux-2.5-frlock/arch/um/kernel/time_kern.c	2003-01-24 14:54:12.000000000 -0800
@@ -21,7 +21,7 @@
 
 u64 jiffies_64;
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 int hz(void)
 {
@@ -57,9 +57,9 @@
 void um_timer(int irq, void *dev, struct pt_regs *regs)
 {
 	do_timer(regs);
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 	timer();
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 long um_time(int * tloc)
diff -urN -X dontdiff linux-2.5.59/arch/v850/kernel/time.c linux-2.5-frlock/arch/v850/kernel/time.c
--- linux-2.5.59/arch/v850/kernel/time.c	2003-01-17 09:42:24.000000000 -0800
+++ linux-2.5-frlock/arch/v850/kernel/time.c	2003-01-24 14:54:12.000000000 -0800
@@ -107,7 +107,7 @@
 #endif /* 0 */
 }
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 
 /*
  * This version of gettimeofday has near microsecond resolution.
@@ -118,23 +118,25 @@
 	extern volatile unsigned long lost_ticks;
 	unsigned long lost;
 #endif
-	unsigned long flags;
 	unsigned long usec, sec;
+	unsigned long seq;
+
+	do {
+		seq = fr_read_begin(&xtime_lock);
 
-	read_lock_irqsave (&xtime_lock, flags);
 #if 0
-	usec = mach_gettimeoffset ? mach_gettimeoffset () : 0;
+		usec = mach_gettimeoffset ? mach_gettimeoffset () : 0;
 #else
-	usec = 0;
+		usec = 0;
 #endif
 #if 0 /* DAVIDM later if possible */
-	lost = lost_ticks;
-	if (lost)
-		usec += lost * (1000000/HZ);
+		lost = lost_ticks;
+		if (lost)
+			usec += lost * (1000000/HZ);
 #endif
-	sec = xtime.tv_sec;
-	usec += xtime.tv_nsec / 1000;
-	read_unlock_irqrestore (&xtime_lock, flags);
+		sec = xtime.tv_sec;
+		usec += xtime.tv_nsec / 1000;
+	} while (seq != fr_read_end(&xtime_lock));
 
 	while (usec >= 1000000) {
 		usec -= 1000000;
@@ -147,7 +149,7 @@
 
 void do_settimeofday (struct timeval *tv)
 {
-	write_lock_irq (&xtime_lock);
+	fr_write_lock_irq (&xtime_lock);
 
 	/* This is revolting. We need to set the xtime.tv_nsec
 	 * correctly. However, the value in this location is
@@ -172,7 +174,7 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq (&xtime_lock);
+	fr_write_unlock_irq (&xtime_lock);
 }
 
 static int timer_dev_id;
diff -urN -X dontdiff linux-2.5.59/arch/x86_64/kernel/time.c linux-2.5-frlock/arch/x86_64/kernel/time.c
--- linux-2.5.59/arch/x86_64/kernel/time.c	2003-01-17 09:42:24.000000000 -0800
+++ linux-2.5-frlock/arch/x86_64/kernel/time.c	2003-01-21 13:20:21.000000000 -0800
@@ -27,7 +27,7 @@
 
 u64 jiffies_64; 
 
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 
 unsigned int cpu_khz;					/* TSC clocks / usec, not used here */
@@ -70,21 +70,22 @@
 
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags, t;
+	unsigned long flags, t, seq;
  	unsigned int sec, usec;
 
-	read_lock_irqsave(&xtime_lock, flags);
-	spin_lock(&time_offset_lock);
+	spin_lock_irqsave(&time_offset_lock, flags);
+	do {
+		seq = fr_read_begin(&xtime_lock);
+
+		sec = xtime.tv_sec;
+		usec = xtime.tv_nsec / 1000;
+
+		t = (jiffies - wall_jiffies) * (1000000L / HZ) + do_gettimeoffset();
+		if (t > timeoffset) timeoffset = t;
+		usec += timeoffset;
 
-	sec = xtime.tv_sec;
-	usec = xtime.tv_nsec / 1000;
-
-	t = (jiffies - wall_jiffies) * (1000000L / HZ) + do_gettimeoffset();
-	if (t > timeoffset) timeoffset = t;
-	usec += timeoffset;
-
-	spin_unlock(&time_offset_lock);
-	read_unlock_irqrestore(&xtime_lock, flags);
+	} while (seq != fr_read_end(&xtime_lock));
+	spin_unlock_irqrestore(&time_offset_lock, flags);
 
 	tv->tv_sec = sec + usec / 1000000;
 	tv->tv_usec = usec % 1000000;
@@ -98,7 +99,7 @@
 
 void do_settimeofday(struct timeval *tv)
 {
-	write_lock_irq(&xtime_lock);
+	fr_write_lock_irq(&xtime_lock);
 	vxtime_lock();
 
 	tv->tv_usec -= do_gettimeoffset() +
@@ -118,7 +119,7 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	write_unlock_irq(&xtime_lock);
+	fr_write_unlock_irq(&xtime_lock);
 }
 
 /*
@@ -201,7 +202,7 @@
  * variables, because both do_timer() and us change them -arca+vojtech
 	 */
 
-	write_lock(&xtime_lock);
+	fr_write_lock(&xtime_lock);
 	vxtime_lock();
 
 	{
@@ -250,7 +251,7 @@
 	}
  
 	vxtime_unlock();
-	write_unlock(&xtime_lock);
+	fr_write_unlock(&xtime_lock);
 }
 
 unsigned long get_cmos_time(void)


Copyright © 2003, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds