diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2014-10-02 10:48:12 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2014-10-02 10:48:12 -0400 |
commit | 94fb1afbcb3e1f8666c9065baded2cb66e72126f (patch) | |
tree | e414f685c7bc7cd88468a0aa834141bec7928e23 /arch/tile | |
parent | bceb7efa6a7e656bfaa67b6f54925e7db75bcd52 (diff) |
tile: switch to using seqlocks for the vDSO time code
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
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 @@ | |||
15 | #ifndef __TILE_VDSO_H__ | 15 | #ifndef __TILE_VDSO_H__ |
16 | #define __TILE_VDSO_H__ | 16 | #define __TILE_VDSO_H__ |
17 | 17 | ||
18 | #include <linux/seqlock.h> | ||
18 | #include <linux/types.h> | 19 | #include <linux/types.h> |
19 | 20 | ||
20 | /* | 21 | /* |
@@ -26,8 +27,8 @@ | |||
26 | */ | 27 | */ |
27 | 28 | ||
28 | struct vdso_data { | 29 | struct vdso_data { |
29 | __u64 tz_update_count; /* Timezone atomicity ctr */ | 30 | seqcount_t tz_seq; /* Timezone seqlock */ |
30 | __u64 tb_update_count; /* Timebase atomicity ctr */ | 31 | seqcount_t tb_seq; /* Timebase seqlock */ |
31 | __u64 xtime_tod_stamp; /* TOD clock for xtime */ | 32 | __u64 xtime_tod_stamp; /* TOD clock for xtime */ |
32 | __u64 xtime_clock_sec; /* Kernel time second */ | 33 | __u64 xtime_clock_sec; /* Kernel time second */ |
33 | __u64 xtime_clock_nsec; /* Kernel time nanosecond */ | 34 | __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) | |||
249 | 249 | ||
250 | void update_vsyscall_tz(void) | 250 | void update_vsyscall_tz(void) |
251 | { | 251 | { |
252 | /* Userspace gettimeofday will spin while this value is odd. */ | 252 | write_seqcount_begin(&vdso_data->tz_seq); |
253 | ++vdso_data->tz_update_count; | ||
254 | smp_wmb(); | ||
255 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; | 253 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; |
256 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; | 254 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; |
257 | smp_wmb(); | 255 | write_seqcount_end(&vdso_data->tz_seq); |
258 | ++vdso_data->tz_update_count; | ||
259 | } | 256 | } |
260 | 257 | ||
261 | void update_vsyscall(struct timekeeper *tk) | 258 | void update_vsyscall(struct timekeeper *tk) |
@@ -266,9 +263,8 @@ void update_vsyscall(struct timekeeper *tk) | |||
266 | if (clock != &cycle_counter_cs) | 263 | if (clock != &cycle_counter_cs) |
267 | return; | 264 | return; |
268 | 265 | ||
269 | /* Userspace gettimeofday will spin while this value is odd. */ | 266 | write_seqcount_begin(&vdso_data->tb_seq); |
270 | ++vdso_data->tb_update_count; | 267 | |
271 | smp_wmb(); | ||
272 | vdso_data->xtime_tod_stamp = tk->tkr.cycle_last; | 268 | vdso_data->xtime_tod_stamp = tk->tkr.cycle_last; |
273 | vdso_data->xtime_clock_sec = tk->xtime_sec; | 269 | vdso_data->xtime_clock_sec = tk->xtime_sec; |
274 | vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec; | 270 | vdso_data->xtime_clock_nsec = tk->tkr.xtime_nsec; |
@@ -276,6 +272,6 @@ void update_vsyscall(struct timekeeper *tk) | |||
276 | vdso_data->wtom_clock_nsec = wtm->tv_nsec; | 272 | vdso_data->wtom_clock_nsec = wtm->tv_nsec; |
277 | vdso_data->mult = tk->tkr.mult; | 273 | vdso_data->mult = tk->tkr.mult; |
278 | vdso_data->shift = tk->tkr.shift; | 274 | vdso_data->shift = tk->tkr.shift; |
279 | smp_wmb(); | 275 | |
280 | ++vdso_data->tb_update_count; | 276 | write_seqcount_end(&vdso_data->tb_seq); |
281 | } | 277 | } |
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) | |||
53 | int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) | 53 | int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) |
54 | { | 54 | { |
55 | cycles_t cycles; | 55 | cycles_t cycles; |
56 | unsigned long count, sec, ns; | 56 | unsigned count; |
57 | volatile struct vdso_data *vdso_data; | 57 | unsigned long sec, ns; |
58 | struct vdso_data *vdso = (struct vdso_data *)get_datapage(); | ||
58 | 59 | ||
59 | vdso_data = (struct vdso_data *)get_datapage(); | ||
60 | /* The use of the timezone is obsolete, normally tz is NULL. */ | 60 | /* The use of the timezone is obsolete, normally tz is NULL. */ |
61 | if (unlikely(tz != NULL)) { | 61 | if (unlikely(tz != NULL)) { |
62 | while (1) { | 62 | do { |
63 | /* Spin until the update finish. */ | 63 | count = read_seqcount_begin(&vdso->tz_seq); |
64 | count = vdso_data->tz_update_count; | 64 | tz->tz_minuteswest = vdso->tz_minuteswest; |
65 | if (count & 1) | 65 | tz->tz_dsttime = vdso->tz_dsttime; |
66 | continue; | 66 | } while (unlikely(read_seqcount_retry(&vdso->tz_seq, count))); |
67 | |||
68 | tz->tz_minuteswest = vdso_data->tz_minuteswest; | ||
69 | tz->tz_dsttime = vdso_data->tz_dsttime; | ||
70 | |||
71 | /* Check whether updated, read again if so. */ | ||
72 | if (count == vdso_data->tz_update_count) | ||
73 | break; | ||
74 | } | ||
75 | } | 67 | } |
76 | 68 | ||
77 | if (unlikely(tv == NULL)) | 69 | if (unlikely(tv == NULL)) |
78 | return 0; | 70 | return 0; |
79 | 71 | ||
80 | while (1) { | 72 | do { |
81 | /* Spin until the update finish. */ | 73 | count = read_seqcount_begin(&vdso->tb_seq); |
82 | count = vdso_data->tb_update_count; | 74 | sec = vdso->xtime_clock_sec; |
83 | if (count & 1) | 75 | cycles = get_cycles() - vdso->xtime_tod_stamp; |
84 | continue; | 76 | ns = (cycles * vdso->mult) + vdso->xtime_clock_nsec; |
85 | 77 | ns >>= vdso->shift; | |
86 | sec = vdso_data->xtime_clock_sec; | ||
87 | cycles = get_cycles() - vdso_data->xtime_tod_stamp; | ||
88 | ns = (cycles * vdso_data->mult) + vdso_data->xtime_clock_nsec; | ||
89 | ns >>= vdso_data->shift; | ||
90 | |||
91 | if (ns >= NSEC_PER_SEC) { | 78 | if (ns >= NSEC_PER_SEC) { |
92 | ns -= NSEC_PER_SEC; | 79 | ns -= NSEC_PER_SEC; |
93 | sec += 1; | 80 | sec += 1; |
94 | } | 81 | } |
95 | 82 | } while (unlikely(read_seqcount_retry(&vdso->tb_seq, count))); | |
96 | /* Check whether updated, read again if so. */ | ||
97 | if (count == vdso_data->tb_update_count) | ||
98 | break; | ||
99 | } | ||
100 | 83 | ||
101 | tv->tv_sec = sec; | 84 | tv->tv_sec = sec; |
102 | tv->tv_usec = ns / 1000; | 85 | tv->tv_usec = ns / 1000; |