Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754343AbaJBPa4 (ORCPT ); Thu, 2 Oct 2014 11:30:56 -0400 Received: from usmamail.tilera.com ([12.216.194.151]:23962 "EHLO USMAMAIL.TILERA.COM" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752510AbaJBPay (ORCPT ); Thu, 2 Oct 2014 11:30:54 -0400 X-CheckPoint: {542D6FAE-2-2100090A-C0000000} Message-ID: <201410021530.s92FUrm1007050@farm-0039.internal.tilera.com> From: Chris Metcalf Date: Thu, 2 Oct 2014 10:48:12 -0400 Subject: [PATCH v3 1/2] tile: switch to using seqlocks for the vDSO time code To: , Thomas Gleixner , John Stultz , Henrik Austad In-Reply-To: <20141001212439.GA12974@sisyphus.home.austad.us> References: <20141001212439.GA12974@sisyphus.home.austad.us> <201409301938.s8UJcfY4018093@lab-40.internal.tilera.com> MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Signed-off-by: Chris Metcalf --- arch/tile/include/asm/vdso.h | 5 ++-- arch/tile/kernel/time.c | 16 +++++------- arch/tile/kernel/vdso/vgettimeofday.c | 47 +++++++++++------------------------ 3 files changed, 24 insertions(+), 44 deletions(-) v2: split apart seqlock and new functionality into separate commits v3: rebase onto 3.17-rc7 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 #include /* @@ -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; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/