diff options
author | Andy Lutomirski <luto@MIT.EDU> | 2011-05-23 09:31:27 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-05-24 08:51:28 -0400 |
commit | 0f51f2852ccf0fe38a02d340d0ba625e8e32a863 (patch) | |
tree | 075e1f7c85c4deec2e0ab7509dcafa859842abd9 /arch/x86/vdso | |
parent | 3729db5ca2b2000c660e5a5d0eb68b1053212cab (diff) |
x86-64: Vclock_gettime(CLOCK_MONOTONIC) can't ever see nsec < 0
vclock_gettime's do_monotonic helper can't ever generate a negative
nsec value, so it doesn't need to check whether it's negative. In
the CLOCK_MONOTONIC_COARSE case, ns can't ever exceed 2e9-1, so we
can avoid the loop entirely. This saves a single easily-predicted
branch.
Signed-off-by: Andy Lutomirski <luto@mit.edu>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Borislav Petkov <bp@amd64.org>
Link: http://lkml.kernel.org/r/%3Cd6d528d32c7a21618057cfc9005942a0fe5cb54a.1306156808.git.luto%40mit.edu%3E
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/vdso')
-rw-r--r-- | arch/x86/vdso/vclock_gettime.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 0b873d455bda..28b2c00bd1be 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c | |||
@@ -55,22 +55,6 @@ notrace static noinline int do_realtime(struct timespec *ts) | |||
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | /* Copy of the version in kernel/time.c which we cannot directly access */ | ||
59 | notrace static void | ||
60 | vset_normalized_timespec(struct timespec *ts, long sec, long nsec) | ||
61 | { | ||
62 | while (nsec >= NSEC_PER_SEC) { | ||
63 | nsec -= NSEC_PER_SEC; | ||
64 | ++sec; | ||
65 | } | ||
66 | while (nsec < 0) { | ||
67 | nsec += NSEC_PER_SEC; | ||
68 | --sec; | ||
69 | } | ||
70 | ts->tv_sec = sec; | ||
71 | ts->tv_nsec = nsec; | ||
72 | } | ||
73 | |||
74 | notrace static noinline int do_monotonic(struct timespec *ts) | 58 | notrace static noinline int do_monotonic(struct timespec *ts) |
75 | { | 59 | { |
76 | unsigned long seq, ns, secs; | 60 | unsigned long seq, ns, secs; |
@@ -81,7 +65,17 @@ notrace static noinline int do_monotonic(struct timespec *ts) | |||
81 | secs += gtod->wall_to_monotonic.tv_sec; | 65 | secs += gtod->wall_to_monotonic.tv_sec; |
82 | ns += gtod->wall_to_monotonic.tv_nsec; | 66 | ns += gtod->wall_to_monotonic.tv_nsec; |
83 | } while (unlikely(read_seqretry(>od->lock, seq))); | 67 | } while (unlikely(read_seqretry(>od->lock, seq))); |
84 | vset_normalized_timespec(ts, secs, ns); | 68 | |
69 | /* wall_time_nsec, vgetns(), and wall_to_monotonic.tv_nsec | ||
70 | * are all guaranteed to be nonnegative. | ||
71 | */ | ||
72 | while (ns >= NSEC_PER_SEC) { | ||
73 | ns -= NSEC_PER_SEC; | ||
74 | ++secs; | ||
75 | } | ||
76 | ts->tv_sec = secs; | ||
77 | ts->tv_nsec = ns; | ||
78 | |||
85 | return 0; | 79 | return 0; |
86 | } | 80 | } |
87 | 81 | ||
@@ -106,7 +100,17 @@ notrace static noinline int do_monotonic_coarse(struct timespec *ts) | |||
106 | secs += gtod->wall_to_monotonic.tv_sec; | 100 | secs += gtod->wall_to_monotonic.tv_sec; |
107 | ns += gtod->wall_to_monotonic.tv_nsec; | 101 | ns += gtod->wall_to_monotonic.tv_nsec; |
108 | } while (unlikely(read_seqretry(>od->lock, seq))); | 102 | } while (unlikely(read_seqretry(>od->lock, seq))); |
109 | vset_normalized_timespec(ts, secs, ns); | 103 | |
104 | /* wall_time_nsec and wall_to_monotonic.tv_nsec are | ||
105 | * guaranteed to be between 0 and NSEC_PER_SEC. | ||
106 | */ | ||
107 | if (ns >= NSEC_PER_SEC) { | ||
108 | ns -= NSEC_PER_SEC; | ||
109 | ++secs; | ||
110 | } | ||
111 | ts->tv_sec = secs; | ||
112 | ts->tv_nsec = ns; | ||
113 | |||
110 | return 0; | 114 | return 0; |
111 | } | 115 | } |
112 | 116 | ||