aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2013-02-21 17:51:38 -0500
committerJohn Stultz <john.stultz@linaro.org>2013-03-22 19:20:01 -0400
commit9a7a71b1d0968fc2bd602b7481cde1d4872e01ff (patch)
tree18954e171dcf260a7750ad6be2f70bac7ef63a78 /kernel
parent7e40672d930b369c1984457233ec5557aa53bfb8 (diff)
timekeeping: Split timekeeper_lock into lock and seqcount
We want to shorten the seqcount write hold time. So split the seqlock into a lock and a seqcount. Open code the seqwrite_lock in the places which matter and drop the sequence counter update where it's pointless. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> [jstultz: Merge fixups from CLOCK_TAI collisions] Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/timekeeping.c132
1 files changed, 73 insertions, 59 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index caede71c0a35..5e048e030c62 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -26,7 +26,8 @@
26#include "tick-internal.h" 26#include "tick-internal.h"
27 27
28static struct timekeeper timekeeper; 28static struct timekeeper timekeeper;
29static DEFINE_SEQLOCK(timekeeper_lock); 29static DEFINE_RAW_SPINLOCK(timekeeper_lock);
30static seqcount_t timekeeper_seq;
30 31
31/* flag for if timekeeping is suspended */ 32/* flag for if timekeeping is suspended */
32int __read_mostly timekeeping_suspended; 33int __read_mostly timekeeping_suspended;
@@ -204,8 +205,6 @@ static void update_pvclock_gtod(struct timekeeper *tk)
204 205
205/** 206/**
206 * pvclock_gtod_register_notifier - register a pvclock timedata update listener 207 * pvclock_gtod_register_notifier - register a pvclock timedata update listener
207 *
208 * Must hold write on timekeeper.lock
209 */ 208 */
210int pvclock_gtod_register_notifier(struct notifier_block *nb) 209int pvclock_gtod_register_notifier(struct notifier_block *nb)
211{ 210{
@@ -213,11 +212,10 @@ int pvclock_gtod_register_notifier(struct notifier_block *nb)
213 unsigned long flags; 212 unsigned long flags;
214 int ret; 213 int ret;
215 214
216 write_seqlock_irqsave(&timekeeper_lock, flags); 215 raw_spin_lock_irqsave(&timekeeper_lock, flags);
217 ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb); 216 ret = raw_notifier_chain_register(&pvclock_gtod_chain, nb);
218 /* update timekeeping data */
219 update_pvclock_gtod(tk); 217 update_pvclock_gtod(tk);
220 write_sequnlock_irqrestore(&timekeeper_lock, flags); 218 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
221 219
222 return ret; 220 return ret;
223} 221}
@@ -226,23 +224,21 @@ EXPORT_SYMBOL_GPL(pvclock_gtod_register_notifier);
226/** 224/**
227 * pvclock_gtod_unregister_notifier - unregister a pvclock 225 * pvclock_gtod_unregister_notifier - unregister a pvclock
228 * timedata update listener 226 * timedata update listener
229 *
230 * Must hold write on timekeeper.lock
231 */ 227 */
232int pvclock_gtod_unregister_notifier(struct notifier_block *nb) 228int pvclock_gtod_unregister_notifier(struct notifier_block *nb)
233{ 229{
234 unsigned long flags; 230 unsigned long flags;
235 int ret; 231 int ret;
236 232
237 write_seqlock_irqsave(&timekeeper_lock, flags); 233 raw_spin_lock_irqsave(&timekeeper_lock, flags);
238 ret = raw_notifier_chain_unregister(&pvclock_gtod_chain, nb); 234 ret = raw_notifier_chain_unregister(&pvclock_gtod_chain, nb);
239 write_sequnlock_irqrestore(&timekeeper_lock, flags); 235 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
240 236
241 return ret; 237 return ret;
242} 238}
243EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier); 239EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier);
244 240
245/* must hold write on timekeeper.lock */ 241/* must hold timekeeper_lock */
246static void timekeeping_update(struct timekeeper *tk, bool clearntp) 242static void timekeeping_update(struct timekeeper *tk, bool clearntp)
247{ 243{
248 if (clearntp) { 244 if (clearntp) {
@@ -296,12 +292,12 @@ int __getnstimeofday(struct timespec *ts)
296 s64 nsecs = 0; 292 s64 nsecs = 0;
297 293
298 do { 294 do {
299 seq = read_seqbegin(&timekeeper_lock); 295 seq = read_seqcount_begin(&timekeeper_seq);
300 296
301 ts->tv_sec = tk->xtime_sec; 297 ts->tv_sec = tk->xtime_sec;
302 nsecs = timekeeping_get_ns(tk); 298 nsecs = timekeeping_get_ns(tk);
303 299
304 } while (read_seqretry(&timekeeper_lock, seq)); 300 } while (read_seqcount_retry(&timekeeper_seq, seq));
305 301
306 ts->tv_nsec = 0; 302 ts->tv_nsec = 0;
307 timespec_add_ns(ts, nsecs); 303 timespec_add_ns(ts, nsecs);
@@ -337,11 +333,11 @@ ktime_t ktime_get(void)
337 WARN_ON(timekeeping_suspended); 333 WARN_ON(timekeeping_suspended);
338 334
339 do { 335 do {
340 seq = read_seqbegin(&timekeeper_lock); 336 seq = read_seqcount_begin(&timekeeper_seq);
341 secs = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; 337 secs = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
342 nsecs = timekeeping_get_ns(tk) + tk->wall_to_monotonic.tv_nsec; 338 nsecs = timekeeping_get_ns(tk) + tk->wall_to_monotonic.tv_nsec;
343 339
344 } while (read_seqretry(&timekeeper_lock, seq)); 340 } while (read_seqcount_retry(&timekeeper_seq, seq));
345 /* 341 /*
346 * Use ktime_set/ktime_add_ns to create a proper ktime on 342 * Use ktime_set/ktime_add_ns to create a proper ktime on
347 * 32-bit architectures without CONFIG_KTIME_SCALAR. 343 * 32-bit architectures without CONFIG_KTIME_SCALAR.
@@ -368,12 +364,12 @@ void ktime_get_ts(struct timespec *ts)
368 WARN_ON(timekeeping_suspended); 364 WARN_ON(timekeeping_suspended);
369 365
370 do { 366 do {
371 seq = read_seqbegin(&timekeeper_lock); 367 seq = read_seqcount_begin(&timekeeper_seq);
372 ts->tv_sec = tk->xtime_sec; 368 ts->tv_sec = tk->xtime_sec;
373 nsec = timekeeping_get_ns(tk); 369 nsec = timekeeping_get_ns(tk);
374 tomono = tk->wall_to_monotonic; 370 tomono = tk->wall_to_monotonic;
375 371
376 } while (read_seqretry(&timekeeper_lock, seq)); 372 } while (read_seqcount_retry(&timekeeper_seq, seq));
377 373
378 ts->tv_sec += tomono.tv_sec; 374 ts->tv_sec += tomono.tv_sec;
379 ts->tv_nsec = 0; 375 ts->tv_nsec = 0;
@@ -397,12 +393,12 @@ void timekeeping_clocktai(struct timespec *ts)
397 WARN_ON(timekeeping_suspended); 393 WARN_ON(timekeeping_suspended);
398 394
399 do { 395 do {
400 seq = read_seqbegin(&timekeeper_lock); 396 seq = read_seqcount_begin(&timekeeper_seq);
401 397
402 ts->tv_sec = tk->xtime_sec + tk->tai_offset; 398 ts->tv_sec = tk->xtime_sec + tk->tai_offset;
403 nsecs = timekeeping_get_ns(tk); 399 nsecs = timekeeping_get_ns(tk);
404 400
405 } while (read_seqretry(&timekeeper_lock, seq)); 401 } while (read_seqcount_retry(&timekeeper_seq, seq));
406 402
407 ts->tv_nsec = 0; 403 ts->tv_nsec = 0;
408 timespec_add_ns(ts, nsecs); 404 timespec_add_ns(ts, nsecs);
@@ -445,7 +441,7 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
445 WARN_ON_ONCE(timekeeping_suspended); 441 WARN_ON_ONCE(timekeeping_suspended);
446 442
447 do { 443 do {
448 seq = read_seqbegin(&timekeeper_lock); 444 seq = read_seqcount_begin(&timekeeper_seq);
449 445
450 *ts_raw = tk->raw_time; 446 *ts_raw = tk->raw_time;
451 ts_real->tv_sec = tk->xtime_sec; 447 ts_real->tv_sec = tk->xtime_sec;
@@ -454,7 +450,7 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
454 nsecs_raw = timekeeping_get_ns_raw(tk); 450 nsecs_raw = timekeeping_get_ns_raw(tk);
455 nsecs_real = timekeeping_get_ns(tk); 451 nsecs_real = timekeeping_get_ns(tk);
456 452
457 } while (read_seqretry(&timekeeper_lock, seq)); 453 } while (read_seqcount_retry(&timekeeper_seq, seq));
458 454
459 timespec_add_ns(ts_raw, nsecs_raw); 455 timespec_add_ns(ts_raw, nsecs_raw);
460 timespec_add_ns(ts_real, nsecs_real); 456 timespec_add_ns(ts_real, nsecs_real);
@@ -494,7 +490,8 @@ int do_settimeofday(const struct timespec *tv)
494 if (!timespec_valid_strict(tv)) 490 if (!timespec_valid_strict(tv))
495 return -EINVAL; 491 return -EINVAL;
496 492
497 write_seqlock_irqsave(&timekeeper_lock, flags); 493 raw_spin_lock_irqsave(&timekeeper_lock, flags);
494 write_seqcount_begin(&timekeeper_seq);
498 495
499 timekeeping_forward_now(tk); 496 timekeeping_forward_now(tk);
500 497
@@ -508,7 +505,8 @@ int do_settimeofday(const struct timespec *tv)
508 505
509 timekeeping_update(tk, true); 506 timekeeping_update(tk, true);
510 507<