hrtimer: create hrtimer_quiesce_cpu() to isolate CPU from hrtimers

To isolate CPUs (isolate from hrtimers) from sysfs using cpusets, we need some
support from the hrtimer core. i.e. A routine hrtimer_quiesce_cpu() which would
migrate away all the unpinned hrtimers, but shouldn't touch the pinned ones.

This patch creates this routine.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
[forward port to 3.18]
Signed-off-by: Santosh Shukla <santosh.shukla@linaro.org>
[ohaugan@codeaurora.org: Port to 4.4]
Git-commit: d4d50a0ddc35e58ee95137ba4d14e74fea8b682f
Git-repo: git://git.linaro.org/people/mike.holmes/santosh.shukla/lng-isol.git
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
[rameezmustafa@codeaurora.org: Port to msm-4.9]
Signed-off-by: Syed Rameez Mustafa <rameezmustafa@codeaurora.org>

Change-Id: Icf93622bdeed9c6c28eb1aca1637bc5b9522a533
Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
This commit is contained in:
Viresh Kumar 2015-03-25 12:07:31 +05:30 committed by Gerrit - the friendly Code Review server
parent 06d4745936
commit a67f648836
2 changed files with 47 additions and 11 deletions

View File

@ -344,6 +344,9 @@ DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
/* Exported timer functions: */
/* To be used from cpusets, only */
extern void hrtimer_quiesce_cpu(void *cpup);
/* Initialize timers: */
extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
enum hrtimer_mode mode);

View File

@ -1605,13 +1605,17 @@ int hrtimers_prepare_cpu(unsigned int cpu)
return 0;
}
#ifdef CONFIG_HOTPLUG_CPU
#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_CPUSETS)
static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
struct hrtimer_clock_base *new_base)
struct hrtimer_clock_base *new_base,
bool remove_pinned)
{
struct hrtimer *timer;
struct timerqueue_node *node;
struct timerqueue_head pinned;
int is_pinned;
timerqueue_init_head(&pinned);
while ((node = timerqueue_getnext(&old_base->active))) {
timer = container_of(node, struct hrtimer, node);
@ -1624,6 +1628,13 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
* under us on another CPU
*/
__remove_hrtimer(timer, old_base, HRTIMER_STATE_ENQUEUED, 0);
is_pinned = timer->state & HRTIMER_STATE_PINNED;
if (!remove_pinned && is_pinned) {
timerqueue_add(&pinned, &timer->node);
continue;
}
timer->base = new_base;
/*
* Enqueue the timers on the new cpu. This does not
@ -1635,17 +1646,23 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
*/
enqueue_hrtimer(timer, new_base);
}
/* Re-queue pinned timers for non-hotplug usecase */
while ((node = timerqueue_getnext(&pinned))) {
timer = container_of(node, struct hrtimer, node);
timerqueue_del(&pinned, &timer->node);
enqueue_hrtimer(timer, old_base);
}
}
int hrtimers_dead_cpu(unsigned int scpu)
static void __migrate_hrtimers(unsigned int scpu, bool remove_pinned)
{
struct hrtimer_cpu_base *old_base, *new_base;
unsigned long flags;
int i;
BUG_ON(cpu_online(scpu));
tick_cancel_sched_timer(scpu);
local_irq_disable();
local_irq_save(flags);
old_base = &per_cpu(hrtimer_bases, scpu);
new_base = this_cpu_ptr(&hrtimer_bases);
/*
@ -1657,7 +1674,7 @@ int hrtimers_dead_cpu(unsigned int scpu)
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
migrate_hrtimer_list(&old_base->clock_base[i],
&new_base->clock_base[i]);
&new_base->clock_base[i], remove_pinned);
}
raw_spin_unlock(&old_base->lock);
@ -1665,12 +1682,28 @@ int hrtimers_dead_cpu(unsigned int scpu)
/* Check, if we got expired work to do */
__hrtimer_peek_ahead_timers();
local_irq_enable();
local_irq_restore(flags);
}
#endif /* CONFIG_HOTPLUG_CPU || CONFIG_CPUSETS */
#ifdef CONFIG_HOTPLUG_CPU
int hrtimers_dead_cpu(unsigned int scpu)
{
BUG_ON(cpu_online(scpu));
tick_cancel_sched_timer(scpu);
__migrate_hrtimers(scpu, true);
return 0;
}
#endif /* CONFIG_HOTPLUG_CPU */
#ifdef CONFIG_CPUSETS
void hrtimer_quiesce_cpu(void *cpup)
{
__migrate_hrtimers(*(int *)cpup, false);
}
#endif /* CONFIG_CPUSETS */
void __init hrtimers_init(void)
{
hrtimers_prepare_cpu(smp_processor_id());