Skip to content

Commit 5da7016

Browse files
anna-marialxIngo Molnar
authored andcommitted
hrtimer: Implement support for softirq based hrtimers
hrtimer callbacks are always invoked in hard interrupt context. Several users in tree require soft interrupt context for their callbacks and achieve this by combining a hrtimer with a tasklet. The hrtimer schedules the tasklet in hard interrupt context and the tasklet callback gets invoked in softirq context later. That's suboptimal and aside of that the real-time patch moves most of the hrtimers into softirq context. So adding native support for hrtimers expiring in softirq context is a valuable extension for both mainline and the RT patch set. Each valid hrtimer clock id has two associated hrtimer clock bases: one for timers expiring in hardirq context and one for timers expiring in softirq context. Implement the functionality to associate a hrtimer with the hard or softirq related clock bases and update the relevant functions to take them into account when the next expiry time needs to be evaluated. Add a check into the hard interrupt context handler functions to check whether the first expiring softirq based timer has expired. If it's expired the softirq is raised and the accounting of softirq based timers to evaluate the next expiry time for programming the timer hardware is skipped until the softirq processing has finished. At the end of the softirq processing the regular processing is resumed. Suggested-by: Thomas Gleixner <[email protected]> Suggested-by: Peter Zijlstra <[email protected]> Signed-off-by: Anna-Maria Gleixner <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: John Stultz <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent c458b1d commit 5da7016

File tree

2 files changed

+188
-29
lines changed

2 files changed

+188
-29
lines changed

include/linux/hrtimer.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ enum hrtimer_restart {
103103
* @base: pointer to the timer base (per cpu and per clock)
104104
* @state: state information (See bit values above)
105105
* @is_rel: Set if the timer was armed relative
106+
* @is_soft: Set if hrtimer will be expired in soft interrupt context.
106107
*
107108
* The hrtimer structure must be initialized by hrtimer_init()
108109
*/
@@ -113,6 +114,7 @@ struct hrtimer {
113114
struct hrtimer_clock_base *base;
114115
u8 state;
115116
u8 is_rel;
117+
u8 is_soft;
116118
};
117119

118120
/**
@@ -178,13 +180,18 @@ enum hrtimer_base_type {
178180
* @hres_active: State of high resolution mode
179181
* @in_hrtirq: hrtimer_interrupt() is currently executing
180182
* @hang_detected: The last hrtimer interrupt detected a hang
183+
* @softirq_activated: displays, if the softirq is raised - update of softirq
184+
* related settings is not required then.
181185
* @nr_events: Total number of hrtimer interrupt events
182186
* @nr_retries: Total number of hrtimer interrupt retries
183187
* @nr_hangs: Total number of hrtimer interrupt hangs
184188
* @max_hang_time: Maximum time spent in hrtimer_interrupt
185189
* @expires_next: absolute time of the next event, is required for remote
186-
* hrtimer enqueue
190+
* hrtimer enqueue; it is the total first expiry time (hard
191+
* and soft hrtimer are taken into account)
187192
* @next_timer: Pointer to the first expiring timer
193+
* @softirq_expires_next: Time to check, if soft queues needs also to be expired
194+
* @softirq_next_timer: Pointer to the first expiring softirq based timer
188195
* @clock_base: array of clock bases for this cpu
189196
*
190197
* Note: next_timer is just an optimization for __remove_hrtimer().
@@ -196,9 +203,10 @@ struct hrtimer_cpu_base {
196203
unsigned int cpu;
197204
unsigned int active_bases;
198205
unsigned int clock_was_set_seq;
199-
unsigned int hres_active : 1,
200-
in_hrtirq : 1,
201-
hang_detected : 1;
206+
unsigned int hres_active : 1,
207+
in_hrtirq : 1,
208+
hang_detected : 1,
209+
softirq_activated : 1;
202210
#ifdef CONFIG_HIGH_RES_TIMERS
203211
unsigned int nr_events;
204212
unsigned short nr_retries;
@@ -207,6 +215,8 @@ struct hrtimer_cpu_base {
207215
#endif
208216
ktime_t expires_next;
209217
struct hrtimer *next_timer;
218+
ktime_t softirq_expires_next;
219+
struct hrtimer *softirq_next_timer;
210220
struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];
211221
} ____cacheline_aligned;
212222

@@ -379,7 +389,8 @@ extern void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
379389
* @timer: the timer to be added
380390
* @tim: expiry time
381391
* @mode: timer mode: absolute (HRTIMER_MODE_ABS) or
382-
* relative (HRTIMER_MODE_REL), and pinned (HRTIMER_MODE_PINNED)
392+
* relative (HRTIMER_MODE_REL), and pinned (HRTIMER_MODE_PINNED);
393+
* softirq based mode is considered for debug purpose only!
383394
*/
384395
static inline void hrtimer_start(struct hrtimer *timer, ktime_t tim,
385396
const enum hrtimer_mode mode)

0 commit comments

Comments
 (0)