Commit b508cfda authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Linus Torvalds

[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.
parent 6a91801c
......@@ -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 */
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment