diff options
author | Andy Lutomirski <luto@mit.edu> | 2012-03-23 00:15:51 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2012-03-23 19:49:33 -0400 |
commit | 91ec87d57fc38c529034e853687dfb7756de5406 (patch) | |
tree | 4f88d6a7e0221bdd791a1de6d4c36b17da8337a2 /arch/x86/vdso | |
parent | 88b28adf6fcdd6d10a1cfc7765bb200d7366a265 (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.c | 38 |
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 | ||
114 | notrace static noinline int do_monotonic(struct timespec *ts) | 114 | notrace 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(>od->seq); | 120 | seq = read_seqcount_begin(>od->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(>od->seq, seq))); | 125 | } while (unlikely(read_seqcount_retry(>od->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 | ||
152 | notrace static noinline int do_monotonic_coarse(struct timespec *ts) | 142 | notrace 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(>od->seq); | 146 | seq = read_seqcount_begin(>od->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(>od->seq, seq))); | 149 | } while (unlikely(read_seqcount_retry(>od->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 | ||