diff -urN -X dontdiff linux-2.5.59/arch/i386/kernel/apm.c linux-2.5-seqlock/arch/i386/kernel/apm.c --- linux-2.5.59/arch/i386/kernel/apm.c 2003-01-16 18:21:37.000000000 -0800 +++ linux-2.5-seqlock/arch/i386/kernel/apm.c 2003-01-30 14:48:34.000000000 -0800 @@ -215,6 +215,7 @@ #include #include #include +#include #include #include #include @@ -227,7 +228,6 @@ #include -extern rwlock_t xtime_lock; extern spinlock_t i8253_lock; extern unsigned long get_cmos_time(void); extern void machine_real_restart(unsigned char *, int); @@ -1250,6 +1250,7 @@ { int err; struct apm_user *as; + unsigned long flags; if (pm_send_all(PM_SUSPEND, (void *)3)) { /* Vetoed */ @@ -1264,10 +1265,10 @@ printk(KERN_CRIT "apm: suspend was vetoed, but suspending anyway.\n"); } /* serialize with the timer interrupt */ - write_lock_irq(&xtime_lock); + seq_write_lock(&xtime_lock); /* protect against access to timer chip registers */ - spin_lock(&i8253_lock); + spin_lock_irqsave(&i8253_lock, flags); get_time_diff(); err = set_system_power_state(APM_STATE_SUSPEND); @@ -1275,8 +1276,8 @@ set_time(); ignore_normal_resume = 1; - spin_unlock(&i8253_lock); - write_unlock_irq(&xtime_lock); + spin_unlock_irqrestore(&i8253_lock, flags); + seq_write_unlock(&xtime_lock); if (err == APM_NO_ERROR) err = APM_SUCCESS; @@ -1301,10 +1302,10 @@ int err; /* serialize with the timer interrupt */ - write_lock_irq(&xtime_lock); + seq_write_lock_irq(&xtime_lock); /* If needed, notify drivers here */ get_time_diff(); - write_unlock_irq(&xtime_lock); + seq_write_unlock_irq(&xtime_lock); err = set_system_power_state(APM_STATE_STANDBY); if ((err != APM_SUCCESS) && (err != APM_NO_ERROR)) @@ -1393,9 +1394,9 @@ ignore_bounce = 1; if ((event != APM_NORMAL_RESUME) || (ignore_normal_resume == 0)) { - write_lock_irq(&xtime_lock); + seq_write_lock_irq(&xtime_lock); set_time(); - write_unlock_irq(&xtime_lock); + seq_write_unlock_irq(&xtime_lock); pm_send_all(PM_RESUME, (void *)0); queue_event(event, NULL); } @@ -1410,9 +1411,9 @@ break; case APM_UPDATE_TIME: - write_lock_irq(&xtime_lock); + seq_write_lock_irq(&xtime_lock); set_time(); - write_unlock_irq(&xtime_lock); + seq_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-seqlock/arch/i386/kernel/time.c --- linux-2.5.59/arch/i386/kernel/time.c 2003-01-16 18:22:09.000000000 -0800 +++ linux-2.5-seqlock/arch/i386/kernel/time.c 2003-01-30 11:50:09.000000000 -0800 @@ -70,7 +70,6 @@ unsigned long cpu_khz; /* Detected as we calibrate the TSC */ -extern rwlock_t xtime_lock; extern unsigned long wall_jiffies; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; @@ -87,19 +86,21 @@ */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned 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 = seq_read_lock(&xtime_lock); + + usec = timer->get_offset(); + { + unsigned long lost = jiffies - wall_jiffies; + if (unlikely(lost != 0)) + usec += lost * (1000000 / HZ); + } + sec = xtime.tv_sec; + usec += (xtime.tv_nsec / 1000); + } while (seq_read_unlock(&xtime_lock, seq)); while (usec >= 1000000) { usec -= 1000000; @@ -112,7 +113,7 @@ void do_settimeofday(struct timeval *tv) { - write_lock_irq(&xtime_lock); + seq_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 +134,7 @@ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - write_unlock_irq(&xtime_lock); + seq_write_unlock_irq(&xtime_lock); } /* @@ -279,13 +280,13 @@ * the irq version of write_lock because as just said we have irq * locally disabled. -arca */ - write_lock(&xtime_lock); + seq_write_lock(&xtime_lock); timer->mark_offset(); do_timer_interrupt(irq, NULL, regs); - write_unlock(&xtime_lock); + seq_write_unlock(&xtime_lock); } diff -urN -X dontdiff linux-2.5.59/arch/i386/kernel/timers/timer_pit.c linux-2.5-seqlock/arch/i386/kernel/timers/timer_pit.c --- linux-2.5.59/arch/i386/kernel/timers/timer_pit.c 2003-01-16 18:22:39.000000000 -0800 +++ linux-2.5-seqlock/arch/i386/kernel/timers/timer_pit.c 2003-01-29 15:17:08.000000000 -0800 @@ -76,7 +76,7 @@ static unsigned long get_offset_pit(void) { int count; - + unsigned long flags; static int count_p = LATCH; /* for the first call after boot */ static unsigned long jiffies_p = 0; @@ -85,8 +85,7 @@ */ unsigned long jiffies_t; - /* gets recalled with irq locally disabled */ - spin_lock(&i8253_lock); + spin_lock_irqsave(&i8253_lock, flags); /* timer count may underflow right here */ outb_p(0x00, 0x43); /* latch the count ASAP */ @@ -108,7 +107,7 @@ count = LATCH - 1; } - spin_unlock(&i8253_lock); + spin_unlock_irqrestore(&i8253_lock, flags); /* * avoiding timer inconsistencies (they are rare, but they happen)...