diff options
| author | Stephen Hemminger <shemminger@osdl.org> | 2003-09-16 04:07:17 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@laptop.osdl.org> | 2003-09-16 04:07:17 -0700 |
| commit | b508cfda0f4273049b7dbd6160398cfda7c78cce (patch) | |
| tree | 552cf7f0c79914247a78cdfd5ad2d8f9ba4dd07b | |
| parent | 6a91801c4ef3faff5a7db5e7f6bebe2e91c90f4e (diff) | |
[PATCH] use seq_lock for monotonic time
Monotonic clock code uses reader/writer lock which is prone to same
starvation problems as we saw with xtime. This patch changes it to seq_lock
which is faster and won't starve writers in face of lots of readers.
| -rw-r--r-- | arch/i386/kernel/timers/timer_tsc.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index 1a96686f92d4..af912f4d2cf1 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -39,7 +39,7 @@ static int delay_at_last_interrupt; static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */ static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */ static unsigned long long monotonic_base; -static rwlock_t monotonic_lock = RW_LOCK_UNLOCKED; +static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; /* convert from cycles(64bits) => nanoseconds (64bits) * basic equation: @@ -111,12 +111,14 @@ static unsigned long get_offset_tsc(void) static unsigned long long monotonic_clock_tsc(void) { unsigned long long last_offset, this_offset, base; + unsigned seq; /* atomically read monotonic base & last_offset */ - read_lock_irq(&monotonic_lock); - last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; - base = monotonic_base; - read_unlock_irq(&monotonic_lock); + do { + seq = read_seqbegin(&monotonic_lock); + last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; + base = monotonic_base; + } while (read_seqretry(&monotonic_lock, seq)); /* Read the Time Stamp Counter */ rdtscll(this_offset); @@ -135,7 +137,7 @@ static void mark_offset_tsc(void) unsigned long long this_offset, last_offset; static int lost_count = 0; - write_lock(&monotonic_lock); + write_seqlock(&monotonic_lock); last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; /* * It is important that these two operations happen almost at @@ -204,7 +206,7 @@ static void mark_offset_tsc(void) /* update the monotonic base value */ this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; monotonic_base += cycles_2_ns(this_offset - last_offset); - write_unlock(&monotonic_lock); + write_sequnlock(&monotonic_lock); /* calculate delay_at_last_interrupt */ count = ((LATCH-1) - count) * TICK_SIZE; @@ -236,7 +238,7 @@ static void mark_offset_tsc_hpet(void) unsigned long long this_offset, last_offset; unsigned long offset, temp, hpet_current; - write_lock(&monotonic_lock); + write_seqlock(&monotonic_lock); last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; /* * It is important that these two operations happen almost at @@ -264,7 +266,7 @@ static void mark_offset_tsc_hpet(void) /* update the monotonic base value */ this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low; monotonic_base += cycles_2_ns(this_offset - last_offset); - write_unlock(&monotonic_lock); + write_sequnlock(&monotonic_lock); /* calculate delay_at_last_interrupt */ /* |
