aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/vdso
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@mit.edu>2012-03-23 00:15:51 -0400
committerJohn Stultz <john.stultz@linaro.org>2012-03-23 19:49:33 -0400
commit91ec87d57fc38c529034e853687dfb7756de5406 (patch)
tree4f88d6a7e0221bdd791a1de6d4c36b17da8337a2 /arch/x86/vdso
parent88b28adf6fcdd6d10a1cfc7765bb200d7366a265 (diff)
x86-64: Simplify and optimize vdso clock_gettime monotonic variants
We used to store the wall-to-monotonic offset and the realtime base. It's faster to precompute the monotonic base. This is about a 3% speedup on Sandy Bridge for CLOCK_MONOTONIC. It's much more impressive for CLOCK_MONOTONIC_COARSE. Signed-off-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'arch/x86/vdso')
-rw-r--r--arch/x86/vdso/vclock_gettime.c38
1 files changed, 8 insertions, 30 deletions
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index 944c5e5d6b6a..6eea70b8f384 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -113,27 +113,17 @@ notrace static noinline int do_realtime(struct timespec *ts)
113 113
114notrace static noinline int do_monotonic(struct timespec *ts) 114notrace static noinline int do_monotonic(struct timespec *ts)
115{ 115{
116 unsigned long seq, ns, secs; 116 unsigned long seq, ns;
117 int mode; 117 int mode;
118 118
119 do { 119 do {
120 seq = read_seqcount_begin(&gtod->seq); 120 seq = read_seqcount_begin(&gtod->seq);
121 mode = gtod->clock.vclock_mode; 121 mode = gtod->clock.vclock_mode;
122 secs = gtod->wall_time_sec; 122 ts->tv_sec = gtod->monotonic_time_sec;
123 ns = gtod->wall_time_nsec + vgetns(); 123 ts->tv_nsec = gtod->monotonic_time_nsec;
124 secs += gtod->wall_to_monotonic.tv_sec; 124 ns = vgetns();
125 ns += gtod->wall_to_monotonic.tv_nsec;
126 } while (unlikely(read_seqcount_retry(&gtod->seq, seq))); 125 } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
127 126 timespec_add_ns(ts, ns);
128 /* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec
129 * are all guaranteed to be nonnegative.
130 */
131 while (ns >= NSEC_PER_SEC) {
132 ns -= NSEC_PER_SEC;
133 ++secs;
134 }
135 ts->tv_sec = secs;
136 ts->tv_nsec = ns;
137 127
138 return mode; 128 return mode;
139} 129}
@@ -151,25 +141,13 @@ notrace static noinline int do_realtime_coarse(struct timespec *ts)
151 141
152notrace static noinline int do_monotonic_coarse(struct timespec *ts) 142notrace static noinline int do_monotonic_coarse(struct timespec *ts)
153{ 143{
154 unsigned long seq, ns, secs; 144 unsigned long seq;
155 do { 145 do {
156 seq = read_seqcount_begin(&gtod->seq); 146 seq = read_seqcount_begin(&gtod->seq);
157 secs = gtod->wall_time_coarse.tv_sec; 147 ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
158 ns = gtod->wall_time_coarse.tv_nsec; 148 ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
159 secs += gtod->wall_to_monotonic.tv_sec;
160 ns += gtod->wall_to_monotonic.tv_nsec;
161 } while (unlikely(read_seqcount_retry(&gtod->seq, seq))); 149 } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
162 150
163 /* wall_time_nsec and wall_to_monotonic.tv_nsec are
164 * guaranteed to be between 0 and NSEC_PER_SEC.
165 */
166 if (ns >= NSEC_PER_SEC) {
167 ns -= NSEC_PER_SEC;
168 ++secs;
169 }
170 ts->tv_sec = secs;
171 ts->tv_nsec = ns;
172
173 return 0; 151 return 0;
174} 152}
175 153