aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-03-25 11:57:45 +0530
committerGary S. Robertson <gary.robertson@linaro.org>2015-07-22 16:17:07 -0500
commit169b6b4865eb02c25468c177351b98c3cc8ad8bf (patch)
treee35de6ab3d8264795b2891a925d5a04c61c6d018
parente5319a8a6359c078b8f361950ff8639e68bb4dc8 (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> [forward port to 3.18] Signed-off-by: Santosh Shukla <santosh.shukla@linaro.org>
-rw-r--r--include/linux/hrtimer.h3
-rw-r--r--kernel/time/hrtimer.c13
2 files changed, 14 insertions, 2 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 32a0af13f438..ac8925979df5 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/time/hrtimer.c b/kernel/time/hrtimer.c
index 50eda41e185a..7477c3534349 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -975,7 +975,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);
}
/*
@@ -1044,6 +1048,11 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
timer_stats_hrtimer_set_start_info(timer);
+
+ /* Update pinned state */
+ timer->state &= ~HRTIMER_STATE_PINNED;
+ timer->state |= !!(mode & HRTIMER_MODE_PINNED) << HRTIMER_PINNED_SHIFT;
+
#ifdef CONFIG_MISSED_TIMER_OFFSETS_HIST
{
ktime_t now = new_base->get_time();
@@ -1339,7 +1348,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);
}