1 From 0252b0470f174ee044a41c376d96dbd7b65c69e0 Mon Sep 17 00:00:00 2001
2 From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
3 Date: Fri, 7 Jun 2013 22:37:06 +0200
4 Subject: [PATCH 221/366] kernel/cpu: fix cpu down problem if kthread's cpu is
7 If kthread is pinned to CPUx and CPUx is going down then we get into
9 - first the unplug thread is created
10 - it will set itself to hp->unplug. As a result, every task that is
11 going to take a lock, has to leave the CPU.
12 - the CPU_DOWN_PREPARE notifier are started. The worker thread will
13 start a new process for the "high priority worker".
14 Now kthread would like to take a lock but since it can't leave the CPU
15 it will never complete its task.
17 We could fire the unplug thread after the notifier but then the cpu is
18 no longer marked "online" and the unplug thread will run on CPU0 which
21 So instead the unplug thread is started and kept waiting until the
22 notfier complete their work.
24 Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
26 kernel/cpu.c | 15 +++++++++++++--
27 1 file changed, 13 insertions(+), 2 deletions(-)
29 diff --git a/kernel/cpu.c b/kernel/cpu.c
30 index 4522046..cc095ff 100644
33 @@ -111,6 +111,7 @@ struct hotplug_pcp {
36 struct completion synced;
37 + struct completion unplug_wait;
38 #ifdef CONFIG_PREEMPT_RT_FULL
40 * Note, on PREEMPT_RT, the hotplug lock must save the state of
41 @@ -214,6 +215,7 @@ static int sync_unplug_thread(void *data)
43 struct hotplug_pcp *hp = data;
45 + wait_for_completion(&hp->unplug_wait);
48 wait_for_pinned_cpus(hp);
49 @@ -279,6 +281,14 @@ static void __cpu_unplug_sync(struct hotplug_pcp *hp)
50 wait_for_completion(&hp->synced);
53 +static void __cpu_unplug_wait(unsigned int cpu)
55 + struct hotplug_pcp *hp = &per_cpu(hotplug_pcp, cpu);
57 + complete(&hp->unplug_wait);
58 + wait_for_completion(&hp->synced);
62 * Start the sync_unplug_thread on the target cpu and wait for it to
64 @@ -302,6 +312,7 @@ static int cpu_unplug_begin(unsigned int cpu)
65 tell_sched_cpu_down_begin(cpu);
67 init_completion(&hp->synced);
68 + init_completion(&hp->unplug_wait);
70 hp->sync_tsk = kthread_create(sync_unplug_thread, hp, "sync_unplug/%d", cpu);
71 if (IS_ERR(hp->sync_tsk)) {
72 @@ -317,8 +328,7 @@ static int cpu_unplug_begin(unsigned int cpu)
73 * wait for tasks that are going to enter these sections and
74 * we must not have them block.
76 - __cpu_unplug_sync(hp);
78 + wake_up_process(hp->sync_tsk);
82 @@ -674,6 +684,7 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
86 + __cpu_unplug_wait(cpu);
87 smpboot_park_threads(cpu);
89 /* Notifiers are done. Don't let any more tasks pin this CPU. */