diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 14bc9cfa63..b728cc5345 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -123,6 +123,26 @@ void ktime_get_ts(struct timespec *ts) | |||
| 123 | EXPORT_SYMBOL_GPL(ktime_get_ts); | 123 | EXPORT_SYMBOL_GPL(ktime_get_ts); |
| 124 | 124 | ||
| 125 | /* | 125 | /* |
| 126 | * Get the coarse grained time at the softirq based on xtime and | ||
| 127 | * wall_to_monotonic. | ||
| 128 | */ | ||
| 129 | static void hrtimer_get_softirq_time(struct hrtimer_base *base) | ||
| 130 | { | ||
| 131 | ktime_t xtim, tomono; | ||
| 132 | unsigned long seq; | ||
| 133 | |||
| 134 | do { | ||
| 135 | seq = read_seqbegin(&xtime_lock); | ||
| 136 | xtim = timespec_to_ktime(xtime); | ||
| 137 | tomono = timespec_to_ktime(wall_to_monotonic); | ||
| 138 | |||
| 139 | } while (read_seqretry(&xtime_lock, seq)); | ||
| 140 | |||
| 141 | base[CLOCK_REALTIME].softirq_time = xtim; | ||
| 142 | base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono); | ||
| 143 | } | ||
| 144 | |||
| 145 | /* | ||
| 126 | * Functions and macros which are different for UP/SMP systems are kept in a | 146 | * Functions and macros which are different for UP/SMP systems are kept in a |
| 127 | * single place | 147 | * single place |
| 128 | */ | 148 | */ |
| @@ -586,9 +606,11 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) | |||
| 586 | */ | 606 | */ |
| 587 | static inline void run_hrtimer_queue(struct hrtimer_base *base) | 607 | static inline void run_hrtimer_queue(struct hrtimer_base *base) |
| 588 | { | 608 | { |
| 589 | ktime_t now = base->get_time(); | ||
| 590 | struct rb_node *node; | 609 | struct rb_node *node; |
| 591 | 610 | ||
| 611 | if (base->get_softirq_time) | ||
| 612 | base->softirq_time = base->get_softirq_time(); | ||
| 613 | |||
| 592 | spin_lock_irq(&base->lock); | 614 | spin_lock_irq(&base->lock); |
| 593 | 615 | ||
| 594 | while ((node = base->first)) { | 616 | while ((node = base->first)) { |
| @@ -598,7 +620,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base) | |||
| 598 | void *data; | 620 | void *data; |
| 599 | 621 | ||
| 600 | timer = rb_entry(node, struct hrtimer, node); | 622 | timer = rb_entry(node, struct hrtimer, node); |
| 601 | if (now.tv64 <= timer->expires.tv64) | 623 | if (base->softirq_time.tv64 <= timer->expires.tv64) |
| 602 | break; | 624 | break; |
| 603 | 625 | ||
| 604 | fn = timer->function; | 626 | fn = timer->function; |
| @@ -641,6 +663,8 @@ void hrtimer_run_queues(void) | |||
| 641 | struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); | 663 | struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); |
| 642 | int i; | 664 | int i; |
| 643 | 665 | ||
| 666 | hrtimer_get_softirq_time(base); | ||
| 667 | |||
| 644 | for (i = 0; i < MAX_HRTIMER_BASES; i++) | 668 | for (i = 0; i < MAX_HRTIMER_BASES; i++) |
| 645 | run_hrtimer_queue(&base[i]); | 669 | run_hrtimer_queue(&base[i]); |
| 646 | } | 670 | } |
