aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/hrtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r--kernel/hrtimer.c83
1 files changed, 47 insertions, 36 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index f1c4155b49ac..5ae51f1bc7c8 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -21,6 +21,12 @@
21 * Credits: 21 * Credits:
22 * based on kernel/timer.c 22 * based on kernel/timer.c
23 * 23 *
24 * Help, testing, suggestions, bugfixes, improvements were
25 * provided by:
26 *
27 * George Anzinger, Andrew Morton, Steven Rostedt, Roman Zippel
28 * et. al.
29 *
24 * For licencing details see kernel-base/COPYING 30 * For licencing details see kernel-base/COPYING
25 */ 31 */
26 32
@@ -66,6 +72,12 @@ EXPORT_SYMBOL_GPL(ktime_get_real);
66 72
67/* 73/*
68 * The timer bases: 74 * The timer bases:
75 *
76 * Note: If we want to add new timer bases, we have to skip the two
77 * clock ids captured by the cpu-timers. We do this by holding empty
78 * entries rather than doing math adjustment of the clock ids.
79 * This ensures that we capture erroneous accesses to these clock ids
80 * rather than moving them into the range of valid clock id's.
69 */ 81 */
70 82
71#define MAX_HRTIMER_BASES 2 83#define MAX_HRTIMER_BASES 2
@@ -406,8 +418,19 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
406 /* Switch the timer base, if necessary: */ 418 /* Switch the timer base, if necessary: */
407 new_base = switch_hrtimer_base(timer, base); 419 new_base = switch_hrtimer_base(timer, base);
408 420
409 if (mode == HRTIMER_REL) 421 if (mode == HRTIMER_REL) {
410 tim = ktime_add(tim, new_base->get_time()); 422 tim = ktime_add(tim, new_base->get_time());
423 /*
424 * CONFIG_TIME_LOW_RES is a temporary way for architectures
425 * to signal that they simply return xtime in
426 * do_gettimeoffset(). In this case we want to round up by
427 * resolution when starting a relative timer, to avoid short
428 * timeouts. This will go away with the GTOD framework.
429 */
430#ifdef CONFIG_TIME_LOW_RES
431 tim = ktime_add(tim, base->resolution);
432#endif
433 }
411 timer->expires = tim; 434 timer->expires = tim;
412 435
413 enqueue_hrtimer(timer, new_base); 436 enqueue_hrtimer(timer, new_base);
@@ -483,29 +506,25 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
483} 506}
484 507
485/** 508/**
486 * hrtimer_rebase - rebase an initialized hrtimer to a different base 509 * hrtimer_init - initialize a timer to the given clock
487 * 510 *
488 * @timer: the timer to be rebased 511 * @timer: the timer to be initialized
489 * @clock_id: the clock to be used 512 * @clock_id: the clock to be used
513 * @mode: timer mode abs/rel
490 */ 514 */
491void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id) 515void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
516 enum hrtimer_mode mode)
492{ 517{
493 struct hrtimer_base *bases; 518 struct hrtimer_base *bases;
494 519
520 memset(timer, 0, sizeof(struct hrtimer));
521
495 bases = per_cpu(hrtimer_bases, raw_smp_processor_id()); 522 bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
496 timer->base = &bases[clock_id];
497}
498 523
499/** 524 if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS)
500 * hrtimer_init - initialize a timer to the given clock 525 clock_id = CLOCK_MONOTONIC;
501 * 526
502 * @timer: the timer to be initialized 527 timer->base = &bases[clock_id];
503 * @clock_id: the clock to be used
504 */
505void hrtimer_init(struct hrtimer *timer, const clockid_t clock_id)
506{
507 memset(timer, 0, sizeof(struct hrtimer));
508 hrtimer_rebase(timer, clock_id);
509} 528}
510 529
511/** 530/**
@@ -550,6 +569,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
550 fn = timer->function; 569 fn = timer->function;
551 data = timer->data; 570 data = timer->data;
552 set_curr_timer(base, timer); 571 set_curr_timer(base, timer);
572 timer->state = HRTIMER_RUNNING;
553 __remove_hrtimer(timer, base); 573 __remove_hrtimer(timer, base);
554 spin_unlock_irq(&base->lock); 574 spin_unlock_irq(&base->lock);
555 575
@@ -565,6 +585,10 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
565 585
566 spin_lock_irq(&base->lock); 586 spin_lock_irq(&base->lock);
567 587
588 /* Another CPU has added back the timer */
589 if (timer->state != HRTIMER_RUNNING)
590 continue;
591
568 if (restart == HRTIMER_RESTART) 592 if (restart == HRTIMER_RESTART)
569 enqueue_hrtimer(timer, base); 593 enqueue_hrtimer(timer, base);
570 else 594 else
@@ -638,8 +662,7 @@ schedule_hrtimer_interruptible(struct hrtimer *timer,
638 return schedule_hrtimer(timer, mode); 662 return schedule_hrtimer(timer, mode);
639} 663}
640 664
641static long __sched 665static long __sched nanosleep_restart(struct restart_block *restart)
642nanosleep_restart(struct restart_block *restart, clockid_t clockid)
643{ 666{
644 struct timespec __user *rmtp; 667 struct timespec __user *rmtp;
645 struct timespec tu; 668 struct timespec tu;
@@ -649,7 +672,7 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid)
649 672
650 restart->fn = do_no_restart_syscall; 673 restart->fn = do_no_restart_syscall;
651 674
652 hrtimer_init(&timer, clockid); 675 hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS);
653 676
654 timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; 677 timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
655 678
@@ -669,16 +692,6 @@ nanosleep_restart(struct restart_block *restart, clockid_t clockid)
669 return -ERESTART_RESTARTBLOCK; 692 return -ERESTART_RESTARTBLOCK;
670} 693}
671 694
672static long __sched nanosleep_restart_mono(struct restart_block *restart)
673{
674 return nanosleep_restart(restart, CLOCK_MONOTONIC);
675}
676
677static long __sched nanosleep_restart_real(struct restart_block *restart)
678{
679 return nanosleep_restart(restart, CLOCK_REALTIME);
680}
681
682long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, 695long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
683 const enum hrtimer_mode mode, const clockid_t clockid) 696 const enum hrtimer_mode mode, const clockid_t clockid)
684{ 697{
@@ -687,7 +700,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
687 struct timespec tu; 700 struct timespec tu;
688 ktime_t rem; 701 ktime_t rem;
689 702
690 hrtimer_init(&timer, clockid); 703 hrtimer_init(&timer, clockid, mode);
691 704
692 timer.expires = timespec_to_ktime(*rqtp); 705 timer.expires = timespec_to_ktime(*rqtp);
693 706
@@ -695,7 +708,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
695 if (rem.tv64 <= 0) 708 if (rem.tv64 <= 0)
696 return 0; 709 return 0;
697 710
698 /* Absolute timers do not update the rmtp value: */ 711 /* Absolute timers do not update the rmtp value and restart: */
699 if (mode == HRTIMER_ABS) 712 if (mode == HRTIMER_ABS)
700 return -ERESTARTNOHAND; 713 return -ERESTARTNOHAND;
701 714
@@ -705,11 +718,11 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
705 return -EFAULT; 718 return -EFAULT;
706 719
707 restart = &current_thread_info()->restart_block; 720 restart = &current_thread_info()->restart_block;
708 restart->fn = (clockid == CLOCK_MONOTONIC) ? 721 restart->fn = nanosleep_restart;
709 nanosleep_restart_mono : nanosleep_restart_real;
710 restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF; 722 restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF;
711 restart->arg1 = timer.expires.tv64 >> 32; 723 restart->arg1 = timer.expires.tv64 >> 32;
712 restart->arg2 = (unsigned long) rmtp; 724 restart->arg2 = (unsigned long) rmtp;
725 restart->arg3 = (unsigned long) timer.base->index;
713 726
714 return -ERESTART_RESTARTBLOCK; 727 return -ERESTART_RESTARTBLOCK;
715} 728}
@@ -736,10 +749,8 @@ static void __devinit init_hrtimers_cpu(int cpu)
736 struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu); 749 struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu);
737 int i; 750 int i;
738 751
739 for (i = 0; i < MAX_HRTIMER_BASES; i++) { 752 for (i = 0; i < MAX_HRTIMER_BASES; i++, base++)
740 spin_lock_init(&base->lock); 753 spin_lock_init(&base->lock);
741 base++;
742 }
743} 754}
744 755
745#ifdef CONFIG_HOTPLUG_CPU 756#ifdef CONFIG_HOTPLUG_CPU