diff options
| author | Stephen Hemminger <shemminger@osdl.org> | 2003-02-04 23:25:27 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2003-02-04 23:25:27 -0800 |
| commit | bb59cfa4c9113214f91fa0ce744fd92fe2745039 (patch) | |
| tree | 392951d646a403765ff56681fa3a6f5ae99815ed /arch/ppc/kernel | |
| parent | 62672619d8b2203538f37c05ca167b9a8b3f94d4 (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.c | 33 |
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 */ |
