Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

stop_machine: Kill smp_hotplug_thread->pre_unpark, introduce stop_machine_unpark()

1. Change smpboot_unpark_thread() to check ->selfparking, just
like smpboot_park_thread() does.

2. Introduce stop_machine_unpark() which sets ->enabled and calls
kthread_unpark().

3. Change smpboot_thread_call() and cpu_stop_init() to call
stop_machine_unpark() by hand.

This way:

- IMO the ->selfparking logic becomes more consistent.

- We can kill the smp_hotplug_thread->pre_unpark() method.

- We can easily unpark the stopper thread earlier. Say, we
can move stop_machine_unpark() from smpboot_thread_call()
to sched_cpu_active() as Peter suggests.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: heiko.carstens@de.ibm.com
Link: http://lkml.kernel.org/r/20151009160049.GA10166@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Oleg Nesterov and committed by
Ingo Molnar
c00166d8 d8bc8535

+13 -8
-4
include/linux/smpboot.h
··· 24 24 * parked (cpu offline) 25 25 * @unpark: Optional unpark function, called when the thread is 26 26 * unparked (cpu online) 27 - * @pre_unpark: Optional unpark function, called before the thread is 28 - * unparked (cpu online). This is not guaranteed to be 29 - * called on the target cpu of the thread. Careful! 30 27 * @cpumask: Internal state. To update which threads are unparked, 31 28 * call smpboot_update_cpumask_percpu_thread(). 32 29 * @selfparking: Thread is not parked by the park function. ··· 39 42 void (*cleanup)(unsigned int cpu, bool online); 40 43 void (*park)(unsigned int cpu); 41 44 void (*unpark)(unsigned int cpu); 42 - void (*pre_unpark)(unsigned int cpu); 43 45 cpumask_var_t cpumask; 44 46 bool selfparking; 45 47 const char *thread_comm;
+1
include/linux/stop_machine.h
··· 34 34 int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); 35 35 int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); 36 36 void stop_machine_park(int cpu); 37 + void stop_machine_unpark(int cpu); 37 38 38 39 #else /* CONFIG_SMP */ 39 40
+1
kernel/cpu.c
··· 475 475 476 476 case CPU_DOWN_FAILED: 477 477 case CPU_ONLINE: 478 + stop_machine_unpark(cpu); 478 479 smpboot_unpark_threads(cpu); 479 480 break; 480 481
+2 -3
kernel/smpboot.c
··· 222 222 { 223 223 struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); 224 224 225 - if (ht->pre_unpark) 226 - ht->pre_unpark(cpu); 227 - kthread_unpark(tsk); 225 + if (!ht->selfparking) 226 + kthread_unpark(tsk); 228 227 } 229 228 230 229 void smpboot_unpark_threads(unsigned int cpu)
+9 -1
kernel/stop_machine.c
··· 513 513 spin_unlock_irq(&stopper->lock); 514 514 } 515 515 516 + void stop_machine_unpark(int cpu) 517 + { 518 + struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); 519 + 520 + cpu_stop_unpark(cpu); 521 + kthread_unpark(stopper->thread); 522 + } 523 + 516 524 static struct smp_hotplug_thread cpu_stop_threads = { 517 525 .store = &cpu_stopper.thread, 518 526 .thread_should_run = cpu_stop_should_run, ··· 529 521 .create = cpu_stop_create, 530 522 .setup = cpu_stop_unpark, 531 523 .park = cpu_stop_park, 532 - .pre_unpark = cpu_stop_unpark, 533 524 .selfparking = true, 534 525 }; 535 526 ··· 544 537 } 545 538 546 539 BUG_ON(smpboot_register_percpu_thread(&cpu_stop_threads)); 540 + stop_machine_unpark(raw_smp_processor_id()); 547 541 stop_machine_initialized = true; 548 542 return 0; 549 543 }