x86: vdso: Use seqcount instead of seqlock
Thomas Gleixner [Tue, 28 Feb 2012 19:46:04 +0000 (19:46 +0000)]
The update of the vdso data happens under xtime_lock, so adding a
nested lock is pointless. Just use a seqcount to sync the readers.

Reviewed-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>

arch/x86/include/asm/vgtod.h
arch/x86/kernel/vsyscall_64.c
arch/x86/vdso/vclock_gettime.c

index 815285b..1f00717 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/clocksource.h>
 
 struct vsyscall_gtod_data {
-       seqlock_t       lock;
+       seqcount_t      seq;
 
        /* open coded 'struct timespec' */
        time_t          wall_time_sec;
index 33385c1..cdc95a7 100644 (file)
 #include "vsyscall_trace.h"
 
 DEFINE_VVAR(int, vgetcpu_mode);
-DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data) =
-{
-       .lock = __SEQLOCK_UNLOCKED(__vsyscall_gtod_data.lock),
-};
+DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
 
 static enum { EMULATE, NATIVE, NONE } vsyscall_mode = EMULATE;
 
@@ -86,9 +83,7 @@ void update_vsyscall_tz(void)
 void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
                        struct clocksource *clock, u32 mult)
 {
-       unsigned long flags;
-
-       write_seqlock_irqsave(&vsyscall_gtod_data.lock, flags);
+       write_seqcount_begin(&vsyscall_gtod_data.seq);
 
        /* copy vsyscall data */
        vsyscall_gtod_data.clock.vclock_mode    = clock->archdata.vclock_mode;
@@ -101,7 +96,7 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
        vsyscall_gtod_data.wall_to_monotonic    = *wtm;
        vsyscall_gtod_data.wall_time_coarse     = __current_kernel_time();
 
-       write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
+       write_seqcount_end(&vsyscall_gtod_data.seq);
 }
 
 static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
index 7eeb1f6..944c5e5 100644 (file)
@@ -100,12 +100,12 @@ notrace static noinline int do_realtime(struct timespec *ts)
        int mode;
 
        do {
-               seq = read_seqbegin(&gtod->lock);
+               seq = read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                ts->tv_sec = gtod->wall_time_sec;
                ts->tv_nsec = gtod->wall_time_nsec;
                ns = vgetns();
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
 
        timespec_add_ns(ts, ns);
        return mode;
@@ -117,13 +117,13 @@ notrace static noinline int do_monotonic(struct timespec *ts)
        int mode;
 
        do {
-               seq = read_seqbegin(&gtod->lock);
+               seq = read_seqcount_begin(&gtod->seq);
                mode = gtod->clock.vclock_mode;
                secs = gtod->wall_time_sec;
                ns = gtod->wall_time_nsec + vgetns();
                secs += gtod->wall_to_monotonic.tv_sec;
                ns += gtod->wall_to_monotonic.tv_nsec;
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
 
        /* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec
         * are all guaranteed to be nonnegative.
@@ -142,10 +142,10 @@ notrace static noinline int do_realtime_coarse(struct timespec *ts)
 {
        unsigned long seq;
        do {
-               seq = read_seqbegin(&gtod->lock);
+               seq = read_seqcount_begin(&gtod->seq);
                ts->tv_sec = gtod->wall_time_coarse.tv_sec;
                ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
        return 0;
 }
 
@@ -153,12 +153,12 @@ notrace static noinline int do_monotonic_coarse(struct timespec *ts)
 {
        unsigned long seq, ns, secs;
        do {
-               seq = read_seqbegin(&gtod->lock);
+               seq = read_seqcount_begin(&gtod->seq);
                secs = gtod->wall_time_coarse.tv_sec;
                ns = gtod->wall_time_coarse.tv_nsec;
                secs += gtod->wall_to_monotonic.tv_sec;
                ns += gtod->wall_to_monotonic.tv_nsec;
-       } while (unlikely(read_seqretry(&gtod->lock, seq)));
+       } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
 
        /* wall_time_nsec and wall_to_monotonic.tv_nsec are
         * guaranteed to be between 0 and NSEC_PER_SEC.