summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2016-09-16 15:49:32 -0400
committerTejun Heo <tj@kernel.org>2016-09-17 13:18:21 -0400
commit3347fa0928210d96aaa2bd6cd5a8391d5e630873 (patch)
tree6b2b82cee1af9a916679e9713878ceaf81d13e45 /init
parentfa07fb6a4ecad41d373eaf1574b9d54b4f0c1e75 (diff)
workqueue: make workqueue available early during boot
Workqueue is currently initialized in an early init call; however, there are cases where early boot code has to be split and reordered to come after workqueue initialization or the same code path which makes use of workqueues is used both before workqueue initailization and after. The latter cases have to gate workqueue usages with keventd_up() tests, which is nasty and easy to get wrong. Workqueue usages have become widespread and it'd be a lot more convenient if it can be used very early from boot. This patch splits workqueue initialization into two steps. workqueue_init_early() which sets up the basic data structures so that workqueues can be created and work items queued, and workqueue_init() which actually brings up workqueues online and starts executing queued work items. The former step can be done very early during boot once memory allocation, cpumasks and idr are initialized. The latter right after kthreads become available. This allows work item queueing and canceling from very early boot which is what most of these use cases want. * As systemd_wq being initialized doesn't indicate that workqueue is fully online anymore, update keventd_up() to test wq_online instead. The follow-up patches will get rid of all its usages and the function itself. * Flushing doesn't make sense before workqueue is fully initialized. The flush functions trigger WARN and return immediately before fully online. * Work items are never in-flight before fully online. Canceling can always succeed by skipping the flush step. * Some code paths can no longer assume to be called with irq enabled as irq is disabled during early boot. Use irqsave/restore operations instead. v2: Watchdog init, which requires timer to be running, moved from workqueue_init_early() to workqueue_init(). Signed-off-by: Tejun Heo <tj@kernel.org> Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Link: http://lkml.kernel.org/r/CA+55aFx0vPuMuxn00rBSM192n-Du5uxy+4AvKa0SBSOVJeuCGg@mail.gmail.com
Diffstat (limited to 'init')
-rw-r--r--init/main.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/init/main.c b/init/main.c
index a8a58e2794a5..5c4fd68a8671 100644
--- a/init/main.c
+++ b/init/main.c
@@ -551,6 +551,14 @@ asmlinkage __visible void __init start_kernel(void)
551 "Interrupts were enabled *very* early, fixing it\n")) 551 "Interrupts were enabled *very* early, fixing it\n"))
552 local_irq_disable(); 552 local_irq_disable();
553 idr_init_cache(); 553 idr_init_cache();
554
555 /*
556 * Allow workqueue creation and work item queueing/cancelling
557 * early. Work item execution depends on kthreads and starts after
558 * workqueue_init().
559 */
560 workqueue_init_early();
561
554 rcu_init(); 562 rcu_init();
555 563
556 /* trace_printk() and trace points may be used after this */ 564 /* trace_printk() and trace points may be used after this */
@@ -1005,6 +1013,8 @@ static noinline void __init kernel_init_freeable(void)
1005 1013
1006 smp_prepare_cpus(setup_max_cpus); 1014 smp_prepare_cpus(setup_max_cpus);
1007 1015
1016 workqueue_init();
1017
1008 do_pre_smp_initcalls(); 1018 do_pre_smp_initcalls();
1009 lockup_detector_init(); 1019 lockup_detector_init();
1010 1020