aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-07-07 05:27:28 -0400
committerThomas Gleixner <tglx@linutronix.de>2009-07-07 06:47:33 -0400
commit951ed4d36b77ba9fe1ea08fc3c59d8bb6c9bda32 (patch)
tree870456aff2c513c00608f5416d1b7b440fa5f963 /kernel
parentfaf80d62e44dc627efb741f48db50c1858d1667c (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.c4
-rw-r--r--kernel/time/timekeeping.c69
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}
64EXPORT_SYMBOL_GPL(ktime_get); 65EXPORT_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}
132EXPORT_SYMBOL_GPL(ktime_get_ts); 135EXPORT_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
126EXPORT_SYMBOL(getnstimeofday); 126EXPORT_SYMBOL(getnstimeofday);
127 127
128ktime_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}
157EXPORT_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 */
167void 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}
195EXPORT_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