diff options
-rw-r--r-- | include/linux/hrtimer.h | 20 | ||||
-rw-r--r-- | kernel/hrtimer.c | 28 |
2 files changed, 38 insertions, 10 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 6401c31d6add..64e2754ca734 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -72,14 +72,16 @@ struct hrtimer { | |||
72 | /** | 72 | /** |
73 | * struct hrtimer_base - the timer base for a specific clock | 73 | * struct hrtimer_base - the timer base for a specific clock |
74 | * | 74 | * |
75 | * @index: clock type index for per_cpu support when moving a timer | 75 | * @index: clock type index for per_cpu support when moving a timer |
76 | * to a base on another cpu. | 76 | * to a base on another cpu. |
77 | * @lock: lock protecting the base and associated timers | 77 | * @lock: lock protecting the base and associated timers |
78 | * @active: red black tree root node for the active timers | 78 | * @active: red black tree root node for the active timers |
79 | * @first: pointer to the timer node which expires first | 79 | * @first: pointer to the timer node which expires first |
80 | * @resolution: the resolution of the clock, in nanoseconds | 80 | * @resolution: the resolution of the clock, in nanoseconds |
81 | * @get_time: function to retrieve the current time of the clock | 81 | * @get_time: function to retrieve the current time of the clock |
82 | * @curr_timer: the timer which is executing a callback right now | 82 | * @get_sofirq_time: function to retrieve the current time from the softirq |
83 | * @curr_timer: the timer which is executing a callback right now | ||
84 | * @softirq_time: the time when running the hrtimer queue in the softirq | ||
83 | */ | 85 | */ |
84 | struct hrtimer_base { | 86 | struct hrtimer_base { |
85 | clockid_t index; | 87 | clockid_t index; |
@@ -88,7 +90,9 @@ struct hrtimer_base { | |||
88 | struct rb_node *first; | 90 | struct rb_node *first; |
89 | ktime_t resolution; | 91 | ktime_t resolution; |
90 | ktime_t (*get_time)(void); | 92 | ktime_t (*get_time)(void); |
93 | ktime_t (*get_softirq_time)(void); | ||
91 | struct hrtimer *curr_timer; | 94 | struct hrtimer *curr_timer; |
95 | ktime_t softirq_time; | ||
92 | }; | 96 | }; |
93 | 97 | ||
94 | /* | 98 | /* |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 14bc9cfa6399..b728cc53452b 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 | } |