| From a1060d38c1154339447e8810c1cd5cf99b8d2f7b Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Thu, 14 Feb 2013 22:36:59 +0100 |
| Subject: [PATCH] timekeeping: Split jiffies seqlock |
| |
| Replace jiffies_lock seqlock with a simple seqcounter and a rawlock so |
| it can be taken in atomic context on RT. |
| |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| |
| diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c |
| index 555e21f7b966..a5d6435fabbb 100644 |
| --- a/kernel/time/jiffies.c |
| +++ b/kernel/time/jiffies.c |
| @@ -74,7 +74,8 @@ static struct clocksource clocksource_jiffies = { |
| .max_cycles = 10, |
| }; |
| |
| -__cacheline_aligned_in_smp DEFINE_SEQLOCK(jiffies_lock); |
| +__cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(jiffies_lock); |
| +__cacheline_aligned_in_smp seqcount_t jiffies_seq; |
| |
| #if (BITS_PER_LONG < 64) |
| u64 get_jiffies_64(void) |
| @@ -83,9 +84,9 @@ u64 get_jiffies_64(void) |
| u64 ret; |
| |
| do { |
| - seq = read_seqbegin(&jiffies_lock); |
| + seq = read_seqcount_begin(&jiffies_seq); |
| ret = jiffies_64; |
| - } while (read_seqretry(&jiffies_lock, seq)); |
| + } while (read_seqcount_retry(&jiffies_seq, seq)); |
| return ret; |
| } |
| EXPORT_SYMBOL(get_jiffies_64); |
| diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c |
| index 4fcd99e12aa0..5a47f2e98faf 100644 |
| --- a/kernel/time/tick-common.c |
| +++ b/kernel/time/tick-common.c |
| @@ -79,13 +79,15 @@ int tick_is_oneshot_available(void) |
| static void tick_periodic(int cpu) |
| { |
| if (tick_do_timer_cpu == cpu) { |
| - write_seqlock(&jiffies_lock); |
| + raw_spin_lock(&jiffies_lock); |
| + write_seqcount_begin(&jiffies_seq); |
| |
| /* Keep track of the next tick event */ |
| tick_next_period = ktime_add(tick_next_period, tick_period); |
| |
| do_timer(1); |
| - write_sequnlock(&jiffies_lock); |
| + write_seqcount_end(&jiffies_seq); |
| + raw_spin_unlock(&jiffies_lock); |
| update_wall_time(); |
| } |
| |
| @@ -157,9 +159,9 @@ void tick_setup_periodic(struct clock_event_device *dev, int broadcast) |
| ktime_t next; |
| |
| do { |
| - seq = read_seqbegin(&jiffies_lock); |
| + seq = read_seqcount_begin(&jiffies_seq); |
| next = tick_next_period; |
| - } while (read_seqretry(&jiffies_lock, seq)); |
| + } while (read_seqcount_retry(&jiffies_seq, seq)); |
| |
| clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT); |
| |
| diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c |
| index 204fdc86863d..c01bd7165c34 100644 |
| --- a/kernel/time/tick-sched.c |
| +++ b/kernel/time/tick-sched.c |
| @@ -62,7 +62,8 @@ static void tick_do_update_jiffies64(ktime_t now) |
| return; |
| |
| /* Reevaluate with jiffies_lock held */ |
| - write_seqlock(&jiffies_lock); |
| + raw_spin_lock(&jiffies_lock); |
| + write_seqcount_begin(&jiffies_seq); |
| |
| delta = ktime_sub(now, last_jiffies_update); |
| if (delta.tv64 >= tick_period.tv64) { |
| @@ -85,10 +86,12 @@ static void tick_do_update_jiffies64(ktime_t now) |
| /* Keep the tick_next_period variable up to date */ |
| tick_next_period = ktime_add(last_jiffies_update, tick_period); |
| } else { |
| - write_sequnlock(&jiffies_lock); |
| + write_seqcount_end(&jiffies_seq); |
| + raw_spin_unlock(&jiffies_lock); |
| return; |
| } |
| - write_sequnlock(&jiffies_lock); |
| + write_seqcount_end(&jiffies_seq); |
| + raw_spin_unlock(&jiffies_lock); |
| update_wall_time(); |
| } |
| |
| @@ -99,12 +102,14 @@ static ktime_t tick_init_jiffy_update(void) |
| { |
| ktime_t period; |
| |
| - write_seqlock(&jiffies_lock); |
| + raw_spin_lock(&jiffies_lock); |
| + write_seqcount_begin(&jiffies_seq); |
| /* Did we start the jiffies update yet ? */ |
| if (last_jiffies_update.tv64 == 0) |
| last_jiffies_update = tick_next_period; |
| period = last_jiffies_update; |
| - write_sequnlock(&jiffies_lock); |
| + write_seqcount_end(&jiffies_seq); |
| + raw_spin_unlock(&jiffies_lock); |
| return period; |
| } |
| |
| @@ -670,10 +675,10 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts, |
| |
| /* Read jiffies and the time when jiffies were updated last */ |
| do { |
| - seq = read_seqbegin(&jiffies_lock); |
| + seq = read_seqcount_begin(&jiffies_seq); |
| basemono = last_jiffies_update.tv64; |
| basejiff = jiffies; |
| - } while (read_seqretry(&jiffies_lock, seq)); |
| + } while (read_seqcount_retry(&jiffies_seq, seq)); |
| ts->last_jiffies = basejiff; |
| |
| if (rcu_needs_cpu(basemono, &next_rcu) || |
| diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c |
| index 3b65746c7f15..7c7d945d202d 100644 |
| --- a/kernel/time/timekeeping.c |
| +++ b/kernel/time/timekeeping.c |
| @@ -2322,8 +2322,10 @@ EXPORT_SYMBOL(hardpps); |
| */ |
| void xtime_update(unsigned long ticks) |
| { |
| - write_seqlock(&jiffies_lock); |
| + raw_spin_lock(&jiffies_lock); |
| + write_seqcount_begin(&jiffies_seq); |
| do_timer(ticks); |
| - write_sequnlock(&jiffies_lock); |
| + write_seqcount_end(&jiffies_seq); |
| + raw_spin_unlock(&jiffies_lock); |
| update_wall_time(); |
| } |
| diff --git a/kernel/time/timekeeping.h b/kernel/time/timekeeping.h |
| index 704f595ce83f..763a3e5121ff 100644 |
| --- a/kernel/time/timekeeping.h |
| +++ b/kernel/time/timekeeping.h |
| @@ -19,7 +19,8 @@ extern void timekeeping_resume(void); |
| extern void do_timer(unsigned long ticks); |
| extern void update_wall_time(void); |
| |
| -extern seqlock_t jiffies_lock; |
| +extern raw_spinlock_t jiffies_lock; |
| +extern seqcount_t jiffies_seq; |
| |
| #define CS_NAME_LEN 32 |
| |
| -- |
| 2.5.0 |
| |