diff options
Diffstat (limited to 'arch/tile')
-rw-r--r-- | arch/tile/include/asm/vdso.h | 5 | ||||
-rw-r--r-- | arch/tile/kernel/time.c | 16 | ||||
-rw-r--r-- | arch/tile/kernel/vdso/vgettimeofday.c | 47 |
3 files changed, 24 insertions, 44 deletions
diff --git a/arch/tile/include/asm/vdso.h b/arch/tile/include/asm/vdso.h index 9f6a78d665fa..d64b0d58a7e9 100644 --- a/arch/tile/include/asm/vdso.h +++ b/arch/tile/include/asm/vdso.h @@ -15,6 +15,7 @@ #ifndef __TILE_VDSO_H__ #define __TILE_VDSO_H__ +#include <linux/seqlock.h> #include <linux/types.h> /* @@ -26,8 +27,8 @@ */ struct vdso_data { - __u64 tz_update_count; /* Timezone atomicity ctr */ - __u64 tb_update_count; /* Timebase atomicity ctr */ + seqcount_t tz_seq; /* Timezone seqlock */ + seqcount_t tb_seq; /* Timebase seqlock */ __u64 xtime_tod_stamp; /* TOD clock for xtime */ __u64 xtime_clock_sec; /* Kernel time second */ __u64 xtime_clock_nsec; /* Kernel time nanosecond */ diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index d8fbc289e680..2fe8323db77e 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -249,13 +249,10 @@ cycles_t ns2cycles(unsigned long nsecs) void update_vsyscall_tz(void) { - /* Userspace gettimeofday will spin while this value is odd. */ - ++vdso_data->tz_update_count; - smp_wmb(); + write_seqcount_begin(&vdso_data->tz_seq); vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; vdso_data->tz_dsttime = sys_tz.tz_dsttime; - smp_wmb(); - ++vdso_data->tz_update_count; + write_seqcount_end(&vdso_data->tz_seq); } void update_vsyscall(struct timekeeper *tk) @@ -266,9 +263,8 @@ void update_vsyscall(struct timekeeper *tk) if (clock != &cycle_counter_cs) return; - /* Userspace gettimeofday will spin while this value is odd. */ - ++vdso_data->tb_update_count; - smp_wmb(); + write_seqcount_begin(&vdso_data->tb_seq); + vdso_data->xtime_tod_stamp = tk->tkr.cycle_last; vdso_data->xtime_clock_sec = tk->xtime_sec; vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec; @@ -276,6 +272,6 @@ void update_vsyscall(struct timekeeper *tk) vdso_data->wtom_clock_nsec = wtm->tv_nsec; vdso_data->mult = tk->tkr.mult; vdso_data->shift = tk->tkr.shift; - smp_wmb(); - ++vdso_data->tb_update_count; + + write_seqcount_end(&vdso_data->tb_seq); } diff --git a/arch/tile/kernel/vdso/vgettimeofday.c b/arch/tile/kernel/vdso/vgettimeofday.c index e933fb9fbf5c..7cff8fbac4f0 100644 --- a/arch/tile/kernel/vdso/vgettimeofday.c +++ b/arch/tile/kernel/vdso/vgettimeofday.c @@ -53,50 +53,33 @@ inline unsigned long get_datapage(void) int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) { cycles_t cycles; - unsigned long count, sec, ns; - volatile struct vdso_data *vdso_data; + unsigned count; + unsigned long sec, ns; + struct vdso_data *vdso = (struct vdso_data *)get_datapage(); - vdso_data = (struct vdso_data *)get_datapage(); /* The use of the timezone is obsolete, normally tz is NULL. */ if (unlikely(tz != NULL)) { - while (1) { - /* Spin until the update finish. */ - count = vdso_data->tz_update_count; - if (count & 1) - continue; - - tz->tz_minuteswest = vdso_data->tz_minuteswest; - tz->tz_dsttime = vdso_data->tz_dsttime; - - /* Check whether updated, read again if so. */ - if (count == vdso_data->tz_update_count) - break; - } + do { + count = read_seqcount_begin(&vdso->tz_seq); + tz->tz_minuteswest = vdso->tz_minuteswest; + tz->tz_dsttime = vdso->tz_dsttime; + } while (unlikely(read_seqcount_retry(&vdso->tz_seq, count))); } if (unlikely(tv == NULL)) return 0; - while (1) { - /* Spin until the update finish. */ - count = vdso_data->tb_update_count; - if (count & 1) - continue; - - sec = vdso_data->xtime_clock_sec; - cycles = get_cycles() - vdso_data->xtime_tod_stamp; - ns = (cycles * vdso_data->mult) + vdso_data->xtime_clock_nsec; - ns >>= vdso_data->shift; - + do { + count = read_seqcount_begin(&vdso->tb_seq); + sec = vdso->xtime_clock_sec; + cycles = get_cycles() - vdso->xtime_tod_stamp; + ns = (cycles * vdso->mult) + vdso->xtime_clock_nsec; + ns >>= vdso->shift; if (ns >= NSEC_PER_SEC) { ns -= NSEC_PER_SEC; sec += 1; } - - /* Check whether updated, read again if so. */ - if (count == vdso_data->tb_update_count) - break; - } + } while (unlikely(read_seqcount_retry(&vdso->tb_seq, count))); tv->tv_sec = sec; tv->tv_usec = ns / 1000; |