* [PATCH] (2/4) 2.5.59 fast reader/writer lock for gettimeofday
@ 2003-01-28 23:42 Stephen Hemminger
2003-01-29 0:24 ` george anzinger
0 siblings, 1 reply; 2+ messages in thread
From: Stephen Hemminger @ 2003-01-28 23:42 UTC (permalink / raw)
To: Linus Torvalds
Cc: Andrea Arcangeli, Andi Kleen, Andrew Morton,
Linux Kernel Mailing List
[-- Attachment #1: Type: text/plain, Size: 110 bytes --]
This is the i386 portion of lockless gettimeofday. It changes locking
of xtime_lock from rwlock to frlock.
[-- Attachment #2: frlock-xtime-i386.patch --]
[-- Type: text/x-patch, Size: 4031 bytes --]
diff -urN -X dontdiff linux-2.5.59/arch/i386/kernel/apm.c linux-2.5-frlock/arch/i386/kernel/apm.c
--- linux-2.5.59/arch/i386/kernel/apm.c 2003-01-17 09:42:14.000000000 -0800
+++ linux-2.5-frlock/arch/i386/kernel/apm.c 2003-01-24 14:54:11.000000000 -0800
@@ -227,7 +227,7 @@
#include <linux/sysrq.h>
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
extern spinlock_t i8253_lock;
extern unsigned long get_cmos_time(void);
extern void machine_real_restart(unsigned char *, int);
@@ -1264,7 +1264,7 @@
printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n");
}
/* serialize with the timer interrupt */
- write_lock_irq(&xtime_lock);
+ fr_write_lock_irq(&xtime_lock);
/* protect against access to timer chip registers */
spin_lock(&i8253_lock);
@@ -1276,7 +1276,7 @@
ignore_normal_resume = 1;
spin_unlock(&i8253_lock);
- write_unlock_irq(&xtime_lock);
+ fr_write_unlock_irq(&xtime_lock);
if (err == APM_NO_ERROR)
err = APM_SUCCESS;
@@ -1301,10 +1301,10 @@
int err;
/* serialize with the timer interrupt */
- write_lock_irq(&xtime_lock);
+ fr_write_lock_irq(&xtime_lock);
/* If needed, notify drivers here */
get_time_diff();
- write_unlock_irq(&xtime_lock);
+ fr_write_unlock_irq(&xtime_lock);
err = set_system_power_state(APM_STATE_STANDBY);
if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
@@ -1393,9 +1393,9 @@
ignore_bounce = 1;
if ((event != APM_NORMAL_RESUME)
|| (ignore_normal_resume == 0)) {
- write_lock_irq(&xtime_lock);
+ fr_write_lock_irq(&xtime_lock);
set_time();
- write_unlock_irq(&xtime_lock);
+ fr_write_unlock_irq(&xtime_lock);
pm_send_all(PM_RESUME, (void *)0);
queue_event(event, NULL);
}
@@ -1410,9 +1410,9 @@
break;
case APM_UPDATE_TIME:
- write_lock_irq(&xtime_lock);
+ fr_write_lock_irq(&xtime_lock);
set_time();
- write_unlock_irq(&xtime_lock);
+ fr_write_unlock_irq(&xtime_lock);
break;
case APM_CRITICAL_SUSPEND:
diff -urN -X dontdiff linux-2.5.59/arch/i386/kernel/time.c linux-2.5-frlock/arch/i386/kernel/time.c
--- linux-2.5.59/arch/i386/kernel/time.c 2003-01-17 09:42:14.000000000 -0800
+++ linux-2.5-frlock/arch/i386/kernel/time.c 2003-01-24 15:06:37.000000000 -0800
@@ -70,7 +70,7 @@
unsigned long cpu_khz; /* Detected as we calibrate the TSC */
-extern rwlock_t xtime_lock;
+extern frlock_t xtime_lock;
extern unsigned long wall_jiffies;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -87,19 +87,21 @@
*/
void do_gettimeofday(struct timeval *tv)
{
- unsigned long flags;
+ unsigned long seq;
unsigned long usec, sec;
- read_lock_irqsave(&xtime_lock, flags);
- usec = timer->get_offset();
- {
- 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 = timer->get_offset();
+ {
+ unsigned long lost = jiffies - wall_jiffies;
+ if (lost)
+ usec += lost * (1000000 / HZ);
+ }
+ sec = xtime.tv_sec;
+ usec += (xtime.tv_nsec / 1000);
+ } while (unlikely(seq != fr_read_end(&xtime_lock)));
while (usec >= 1000000) {
usec -= 1000000;
@@ -112,7 +114,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
@@ -133,7 +135,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);
}
/*
@@ -279,12 +281,12 @@
* 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);
timer->mark_offset();
do_timer_interrupt(irq, NULL, regs);
- write_unlock(&xtime_lock);
+ fr_write_unlock(&xtime_lock);
}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] (2/4) 2.5.59 fast reader/writer lock for gettimeofday
2003-01-28 23:42 [PATCH] (2/4) 2.5.59 fast reader/writer lock for gettimeofday Stephen Hemminger
@ 2003-01-29 0:24 ` george anzinger
0 siblings, 0 replies; 2+ messages in thread
From: george anzinger @ 2003-01-29 0:24 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Linus Torvalds, Andrea Arcangeli, Andi Kleen, Andrew Morton,
Linux Kernel Mailing List
One wonders if it wouldn't be better to put the div in
gettimeofday() outside of the lock region, see below... It
makes the while condition even more unlikely.
-g
~snip~
> diff -urN -X dontdiff linux-2.5.59/arch/i386/kernel/time.c linux-2.5-frlock/arch/i386/kernel/time.c
> --- linux-2.5.59/arch/i386/kernel/time.c 2003-01-17 09:42:14.000000000 -0800
> +++ linux-2.5-frlock/arch/i386/kernel/time.c 2003-01-24 15:06:37.000000000 -0800
> @@ -70,7 +70,7 @@
>
> unsigned long cpu_khz; /* Detected as we calibrate the TSC */
>
> -extern rwlock_t xtime_lock;
> +extern frlock_t xtime_lock;
> extern unsigned long wall_jiffies;
>
> spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
> @@ -87,19 +87,21 @@
> */
> void do_gettimeofday(struct timeval *tv)
> {
> - unsigned long flags;
> + unsigned long seq;
++++> unsigned long xtimensec;
> unsigned long usec, sec;
>
> - read_lock_irqsave(&xtime_lock, flags);
> - usec = timer->get_offset();
> - {
> - 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 = timer->get_offset();
> + {
> + unsigned long lost = jiffies - wall_jiffies;
> + if (lost)
> + usec += lost * (1000000 / HZ);
> + }
> + sec = xtime.tv_sec;
----> + usec += (xtime.tv_nsec / 1000);
++++> + xtimensec = xtime.tv_nsec;
> + } while (unlikely(seq != fr_read_end(&xtime_lock)));
>
++++> usec += xtimensec / 1000;
> while (usec >= 1000000) {
> usec -= 1000000;
> @@ -112,7 +114,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
> @@ -133,7 +135,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);
> }
>
> /*
> @@ -279,12 +281,12 @@
> * 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);
>
> timer->mark_offset();
>
> do_timer_interrupt(irq, NULL, regs);
>
> - write_unlock(&xtime_lock);
> + fr_write_unlock(&xtime_lock);
>
> }
--
George Anzinger george@mvista.com
High-res-timers:
http://sourceforge.net/projects/high-res-timers/
Preemption patch:
http://www.kernel.org/pub/linux/kernel/people/rml
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2003-01-29 0:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-01-28 23:42 [PATCH] (2/4) 2.5.59 fast reader/writer lock for gettimeofday Stephen Hemminger
2003-01-29 0:24 ` george anzinger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox