Skip to content

Commit

Permalink
sched: Add irq_{enter,exit}() to scheduler_ipi()
Browse files Browse the repository at this point in the history
Ensure scheduler_ipi() calls irq_{enter,exit} when it does some actual
work. Traditionally we never did any actual work from the resched IPI
and all magic happened in the return from interrupt path.

Now that we do do some work, we need to ensure irq_{enter,exit} are
called so that we don't confuse things.

This affects things like timekeeping, NO_HZ and RCU, basically
everything with a hook in irq_enter/exit.

Explicit examples of things going wrong are:

  sched_clock_cpu() -- has a callback when leaving NO_HZ state to take
                    a new reading from GTOD and TSC. Without this
                    callback, time is stuck in the past.

  RCU -- needs in_irq() to work in order to avoid some nasty deadlocks

Signed-off-by: Peter Zijlstra <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
  • Loading branch information
Peter Zijlstra authored and paulmck committed Jul 20, 2011
1 parent 10f39bb commit c5d753a
Showing 1 changed file with 38 additions and 6 deletions.
44 changes: 38 additions & 6 deletions kernel/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -2544,13 +2544,9 @@ static int ttwu_remote(struct task_struct *p, int wake_flags)
}

#ifdef CONFIG_SMP
static void sched_ttwu_pending(void)
static void sched_ttwu_do_pending(struct task_struct *list)
{
struct rq *rq = this_rq();
struct task_struct *list = xchg(&rq->wake_list, NULL);

if (!list)
return;

raw_spin_lock(&rq->lock);

Expand All @@ -2563,9 +2559,45 @@ static void sched_ttwu_pending(void)
raw_spin_unlock(&rq->lock);
}

#ifdef CONFIG_HOTPLUG_CPU

static void sched_ttwu_pending(void)
{
struct rq *rq = this_rq();
struct task_struct *list = xchg(&rq->wake_list, NULL);

if (!list)
return;

sched_ttwu_do_pending(list);
}

#endif /* CONFIG_HOTPLUG_CPU */

void scheduler_ipi(void)
{
sched_ttwu_pending();
struct rq *rq = this_rq();
struct task_struct *list = xchg(&rq->wake_list, NULL);

if (!list)
return;

/*
* Not all reschedule IPI handlers call irq_enter/irq_exit, since
* traditionally all their work was done from the interrupt return
* path. Now that we actually do some work, we need to make sure
* we do call them.
*
* Some archs already do call them, luckily irq_enter/exit nest
* properly.
*
* Arguably we should visit all archs and update all handlers,
* however a fair share of IPIs are still resched only so this would
* somewhat pessimize the simple resched case.
*/
irq_enter();
sched_ttwu_do_pending(list);
irq_exit();
}

static void ttwu_queue_remote(struct task_struct *p, int cpu)
Expand Down

0 comments on commit c5d753a

Please sign in to comment.