summaryrefslogtreecommitdiff
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2003-02-04 23:25:27 -0800
committerLinus Torvalds <torvalds@penguin.transmeta.com>2003-02-04 23:25:27 -0800
commitbb59cfa4c9113214f91fa0ce744fd92fe2745039 (patch)
tree392951d646a403765ff56681fa3a6f5ae99815ed /arch/ppc/kernel
parent62672619d8b2203538f37c05ca167b9a8b3f94d4 (diff)
[PATCH] seqlock for xtime
Add "seqlock" infrastructure for doing low-overhead optimistic reader locks (writer increments a sequence number, reader verifies that no writers came in during the critical region, and lots of careful memory barriers to take care of business). Make xtime/get_jiffies_64() use this new locking.
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/time.c33
1 files changed, 17 insertions, 16 deletions
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 14c583e45876..3fef611a7df8 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -76,7 +76,6 @@ extern struct timezone sys_tz;
/* keep track of when we need to update the rtc */
time_t last_rtc_update;
-extern rwlock_t xtime_lock;
/* The decrementer counts down by 128 every 128ns on a 601. */
#define DECREMENTER_COUNT_601 (1000000000 / HZ)
@@ -161,7 +160,7 @@ void timer_interrupt(struct pt_regs * regs)
continue;
/* We are in an interrupt, no need to save/restore flags */
- write_lock(&xtime_lock);
+ write_seqlock(&xtime_lock);
tb_last_stamp = jiffy_stamp;
do_timer(regs);
@@ -191,7 +190,7 @@ void timer_interrupt(struct pt_regs * regs)
/* Try again one minute later */
last_rtc_update += 60;
}
- write_unlock(&xtime_lock);
+ write_sequnlock(&xtime_lock);
}
if ( !disarm_decr[smp_processor_id()] )
set_dec(next_dec);
@@ -213,21 +212,23 @@ void timer_interrupt(struct pt_regs * regs)
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 = read_seqbegin_irqsave(&xtime_lock, flags);
+ 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 (read_seqretry_irqrestore(&xtime_lock, seq, flags));
usec += mulhwu(tb_to_us, tb_ticks_per_jiffy * lost_ticks + delta);
while (usec >= 1000000) {
@@ -243,7 +244,7 @@ void do_settimeofday(struct timeval *tv)
unsigned long flags;
int tb_delta, new_usec, new_sec;
- write_lock_irqsave(&xtime_lock, flags);
+ write_seqlock_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 @@ void do_settimeofday(struct timeval *tv)
time_state = TIME_ERROR; /* p. 24, (a) */
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- write_unlock_irqrestore(&xtime_lock, flags);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
}
/* This function is only called on the boot processor */