diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-07-07 05:27:28 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-07-07 06:47:33 -0400 |
commit | 951ed4d36b77ba9fe1ea08fc3c59d8bb6c9bda32 (patch) | |
tree | 870456aff2c513c00608f5416d1b7b440fa5f963 /kernel | |
parent | faf80d62e44dc627efb741f48db50c1858d1667c (diff) |
timekeeping: optimized ktime_get[_ts] for GENERIC_TIME=y
The generic ktime_get function defined in kernel/hrtimer.c is suboptimial
for GENERIC_TIME=y:
0) | ktime_get() {
0) | ktime_get_ts() {
0) | getnstimeofday() {
0) | read_tod_clock() {
0) 0.601 us | }
0) 1.938 us | }
0) | set_normalized_timespec() {
0) 0.602 us | }
0) 4.375 us | }
0) 5.523 us | }
Overall there are two read_seqbegin/read_seqretry loops and a lot of
unnecessary struct timespec calculations. ktime_get returns a nano second
value which is the sum of xtime, wall_to_monotonic and the nano second
delta from the clock source.
ktime_get can be optimized for GENERIC_TIME=y. The new version only calls
clocksource_read:
0) | ktime_get() {
0) | read_tod_clock() {
0) 0.610 us | }
0) 1.977 us | }
It uses a single read_seqbegin/readseqretry loop and just adds everthing
to a nano second value.
ktime_get_ts is optimized in a similar fashion.
[ tglx: added WARN_ON(timekeeping_suspended) as in getnstimeofday() ]
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Acked-by: john stultz <johnstul@us.ibm.com>
LKML-Reference: <20090707112728.3005244d@skybase>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/hrtimer.c | 4 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 69 |
2 files changed, 73 insertions, 0 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 9002958a96e7..829e0664b72e 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -48,6 +48,7 @@ | |||
48 | 48 | ||
49 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
50 | 50 | ||
51 | #ifndef CONFIG_GENERIC_TIME | ||
51 | /** | 52 | /** |
52 | * ktime_get - get the monotonic time in ktime_t format | 53 | * ktime_get - get the monotonic time in ktime_t format |
53 | * | 54 | * |
@@ -62,6 +63,7 @@ ktime_t ktime_get(void) | |||
62 | return timespec_to_ktime(now); | 63 | return timespec_to_ktime(now); |
63 | } | 64 | } |
64 | EXPORT_SYMBOL_GPL(ktime_get); | 65 | EXPORT_SYMBOL_GPL(ktime_get); |
66 | #endif | ||
65 | 67 | ||
66 | /** | 68 | /** |
67 | * ktime_get_real - get the real (wall-) time in ktime_t format | 69 | * ktime_get_real - get the real (wall-) time in ktime_t format |
@@ -106,6 +108,7 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = | |||
106 | } | 108 | } |
107 | }; | 109 | }; |
108 | 110 | ||
111 | #ifndef CONFIG_GENERIC_TIME | ||
109 | /** | 112 | /** |
110 | * ktime_get_ts - get the monotonic clock in timespec format | 113 | * ktime_get_ts - get the monotonic clock in timespec format |
111 | * @ts: pointer to timespec variable | 114 | * @ts: pointer to timespec variable |
@@ -130,6 +133,7 @@ void ktime_get_ts(struct timespec *ts) | |||
130 | ts->tv_nsec + tomono.tv_nsec); | 133 | ts->tv_nsec + tomono.tv_nsec); |
131 | } | 134 | } |
132 | EXPORT_SYMBOL_GPL(ktime_get_ts); | 135 | EXPORT_SYMBOL_GPL(ktime_get_ts); |
136 | #endif | ||
133 | 137 | ||
134 | /* | 138 | /* |
135 | * Get the coarse grained time at the softirq based on xtime and | 139 | * Get the coarse grained time at the softirq based on xtime and |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index e8c77d9c633a..7a248135c6f2 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -125,6 +125,75 @@ void getnstimeofday(struct timespec *ts) | |||
125 | 125 | ||
126 | EXPORT_SYMBOL(getnstimeofday); | 126 | EXPORT_SYMBOL(getnstimeofday); |
127 | 127 | ||
128 | ktime_t ktime_get(void) | ||
129 | { | ||
130 | cycle_t cycle_now, cycle_delta; | ||
131 | unsigned int seq; | ||
132 | s64 secs, nsecs; | ||
133 | |||
134 | WARN_ON(timekeeping_suspended); | ||
135 | |||
136 | do { | ||
137 | seq = read_seqbegin(&xtime_lock); | ||
138 | secs = xtime.tv_sec + wall_to_monotonic.tv_sec; | ||
139 | nsecs = xtime.tv_nsec + wall_to_monotonic.tv_nsec; | ||
140 | |||
141 | /* read clocksource: */ | ||
142 | cycle_now = clocksource_read(clock); | ||
143 | |||
144 | /* calculate the delta since the last update_wall_time: */ | ||
145 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | ||
146 | |||
147 | /* convert to nanoseconds: */ | ||
148 | nsecs += cyc2ns(clock, cycle_delta); | ||
149 | |||
150 | } while (read_seqretry(&xtime_lock, seq)); | ||
151 | /* | ||
152 | * Use ktime_set/ktime_add_ns to create a proper ktime on | ||
153 | * 32-bit architectures without CONFIG_KTIME_SCALAR. | ||
154 | */ | ||
155 | return ktime_add_ns(ktime_set(secs, 0), nsecs); | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(ktime_get); | ||
158 | |||
159 | /** | ||
160 | * ktime_get_ts - get the monotonic clock in timespec format | ||
161 | * @ts: pointer to timespec variable | ||
162 | * | ||
163 | * The function calculates the monotonic clock from the realtime | ||
164 | * clock and the wall_to_monotonic offset and stores the result | ||
165 | * in normalized timespec format in the variable pointed to by @ts. | ||
166 | */ | ||
167 | void ktime_get_ts(struct timespec *ts) | ||
168 | { | ||
169 | cycle_t cycle_now, cycle_delta; | ||
170 | struct timespec tomono; | ||
171 | unsigned int seq; | ||
172 | s64 nsecs; | ||
173 | |||
174 | WARN_ON(timekeeping_suspended); | ||
175 | |||
176 | do { | ||
177 | seq = read_seqbegin(&xtime_lock); | ||
178 | *ts = xtime; | ||
179 | tomono = wall_to_monotonic; | ||
180 | |||
181 | /* read clocksource: */ | ||
182 | cycle_now = clocksource_read(clock); | ||
183 | |||
184 | /* calculate the delta since the last update_wall_time: */ | ||
185 | cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; | ||
186 | |||
187 | /* convert to nanoseconds: */ | ||
188 | nsecs = cyc2ns(clock, cycle_delta); | ||
189 | |||
190 | } while (read_seqretry(&xtime_lock, seq)); | ||
191 | |||
192 | set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec, | ||
193 | ts->tv_nsec + tomono.tv_nsec + nsecs); | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(ktime_get_ts); | ||
196 | |||
128 | /** | 197 | /** |
129 | * do_gettimeofday - Returns the time of day in a timeval | 198 | * do_gettimeofday - Returns the time of day in a timeval |
130 | * @tv: pointer to the timeval to be set | 199 | * @tv: pointer to the timeval to be set |