aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2014-04-02 12:10:53 +0530
committerAnders Roxell <anders.roxell@linaro.org>2014-09-29 11:11:29 +0200
commit260c0d8430535ddee870e8af6a0ac32000f347aa (patch)
tree16b9659807057ccb899fcf85fc9c96a9b92bc9d5
parentc7ce4156b3f3c6e1ae1838c671372e57305fbce1 (diff)
hrtimer: update timer->state with 'pinned' information
'Pinned' information would be required in migrate_hrtimers() now, as we can migrate non-pinned timers away without a hotplug (i.e. with cpuset.quiesce). And so we may need to identify pinned timers now, as we can't migrate them. This patch reuses the timer->state variable for setting this flag as there were enough number of free bits available in this variable. And there is no point increasing size of this struct by adding another field. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--include/linux/hrtimer.h3
-rw-r--r--kernel/hrtimer.c12
2 files changed, 13 insertions, 2 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index d19a5c2d2270..bce081c68c3b 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -55,6 +55,7 @@ enum hrtimer_restart {
* 0x01 enqueued into rbtree
* 0x02 callback function running
* 0x04 timer is migrated to another cpu
+ * 0x08 timer is pinned to a cpu
*
* Special cases:
* 0x03 callback function running and enqueued
@@ -81,6 +82,8 @@ enum hrtimer_restart {
#define HRTIMER_STATE_ENQUEUED 0x01
#define HRTIMER_STATE_CALLBACK 0x02
#define HRTIMER_STATE_MIGRATE 0x04
+#define HRTIMER_PINNED_SHIFT 3
+#define HRTIMER_STATE_PINNED (1 << HRTIMER_PINNED_SHIFT)
/**
* struct hrtimer - the basic hrtimer structure
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index e0501fe7140d..3570a1393c9e 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -941,7 +941,11 @@ static void __remove_hrtimer(struct hrtimer *timer,
if (!timerqueue_getnext(&base->active))
base->cpu_base->active_bases &= ~(1 << base->index);
out:
- timer->state = newstate;
+ /*
+ * We need to preserve PINNED state here, otherwise we may end up
+ * migrating pinned hrtimers as well.
+ */
+ timer->state = newstate | (timer->state & HRTIMER_STATE_PINNED);
}
/*
@@ -1011,6 +1015,10 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
timer_stats_hrtimer_set_start_info(timer);
+ /* Update pinned state */
+ timer->state &= ~HRTIMER_STATE_PINNED;
+ timer->state |= !!(mode & HRTIMER_MODE_PINNED) << HRTIMER_PINNED_SHIFT;
+
leftmost = enqueue_hrtimer(timer, new_base);
/*
@@ -1274,7 +1282,7 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
* hrtimer_start_range_ns() or in hrtimer_interrupt()
*/
if (restart != HRTIMER_NORESTART) {
- BUG_ON(timer->state != HRTIMER_STATE_CALLBACK);
+ BUG_ON(!(timer->state & HRTIMER_STATE_CALLBACK));
enqueue_hrtimer(timer, base);
}