summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2019-07-30 20:15:25 +0200
committerThomas Gleixner <tglx@linutronix.de>2019-08-01 20:51:19 +0200
commit0ab6a3ddbad40ef5b6b8c2353fd53fa4ecf9c479 (patch)
tree335ebbdf4f72314e51e03ce182e20ac494259f06
parentae6683d815895c2be1e60e1942630fa99488055b (diff)
downloadblackbird-op-linux-0ab6a3ddbad40ef5b6b8c2353fd53fa4ecf9c479.tar.gz
blackbird-op-linux-0ab6a3ddbad40ef5b6b8c2353fd53fa4ecf9c479.zip
hrtimer: Make enqueue mode check work on RT
hrtimer_start_range_ns() has a WARN_ONCE() which verifies that a timer which is marker for softirq expiry is not queued in the hard interrupt base and vice versa. When PREEMPT_RT is enabled, timers which are not explicitely marked to expire in hard interrupt context are deferrred to the soft interrupt. So the regular check would trigger. Change the check, so when PREEMPT_RT is enabled, it is verified that the timers marked for hard interrupt expiry are not tried to be queued for soft interrupt expiry or any of the unmarked and softirq marked is tried to be expired in hard interrupt context. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--include/linux/hrtimer.h3
-rw-r--r--kernel/time/hrtimer.c9
2 files changed, 10 insertions, 2 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 15c2ba6b6316..7d0d0a36a8f4 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -107,6 +107,8 @@ enum hrtimer_restart {
* @state: state information (See bit values above)
* @is_rel: Set if the timer was armed relative
* @is_soft: Set if hrtimer will be expired in soft interrupt context.
+ * @is_hard: Set if hrtimer will be expired in hard interrupt context
+ * even on RT.
*
* The hrtimer structure must be initialized by hrtimer_init()
*/
@@ -118,6 +120,7 @@ struct hrtimer {
u8 state;
u8 is_rel;
u8 is_soft;
+ u8 is_hard;
};
/**
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index dab1ea1a99d0..0ace301a56f4 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1107,9 +1107,13 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
/*
* Check whether the HRTIMER_MODE_SOFT bit and hrtimer.is_soft
- * match.
+ * match on CONFIG_PREEMPT_RT = n. With PREEMPT_RT check the hard
+ * expiry mode because unmarked timers are moved to softirq expiry.
*/
- WARN_ON_ONCE(!(mode & HRTIMER_MODE_SOFT) ^ !timer->is_soft);
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+ WARN_ON_ONCE(!(mode & HRTIMER_MODE_SOFT) ^ !timer->is_soft);
+ else
+ WARN_ON_ONCE(!(mode & HRTIMER_MODE_HARD) ^ !timer->is_hard);
base = lock_hrtimer_base(timer, &flags);
@@ -1288,6 +1292,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
base += hrtimer_clockid_to_base(clock_id);
timer->is_soft = softtimer;
+ timer->is_hard = !softtimer;
timer->base = &cpu_base->clock_base[base];
timerqueue_init(&timer->node);
}
OpenPOWER on IntegriCloud