summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/workqueue.h7
-rw-r--r--init/main.c10
-rw-r--r--kernel/workqueue.c76
3 files changed, 76 insertions, 17 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 26cc1df280d6..91d416f9c0a7 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -358,6 +358,8 @@ extern struct workqueue_struct *system_freezable_wq;
358extern struct workqueue_struct *system_power_efficient_wq; 358extern struct workqueue_struct *system_power_efficient_wq;
359extern struct workqueue_struct *system_freezable_power_efficient_wq; 359extern struct workqueue_struct *system_freezable_power_efficient_wq;
360 360
361extern bool wq_online;
362
361extern struct workqueue_struct * 363extern struct workqueue_struct *
362__alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, 364__alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
363 struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6); 365 struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6);
@@ -594,7 +596,7 @@ static inline bool schedule_delayed_work(struct delayed_work *dwork,
594 */ 596 */
595static inline bool keventd_up(void) 597static inline bool keventd_up(void)
596{ 598{
597 return system_wq != NULL; 599 return wq_online;
598} 600}
599 601
600#ifndef CONFIG_SMP 602#ifndef CONFIG_SMP
@@ -631,4 +633,7 @@ int workqueue_online_cpu(unsigned int cpu);
631int workqueue_offline_cpu(unsigned int cpu); 633int workqueue_offline_cpu(unsigned int cpu);
632#endif 634#endif
633 635
636int __init workqueue_init_early(void);
637int __init workqueue_init(void);
638
634#endif 639#endif
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
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 4eaec8b86d65..15d0811c9e91 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -290,6 +290,8 @@ module_param_named(disable_numa, wq_disable_numa, bool, 0444);
290static bool wq_power_efficient = IS_ENABLED(CONFIG_WQ_POWER_EFFICIENT_DEFAULT); 290static bool wq_power_efficient = IS_ENABLED(CONFIG_WQ_POWER_EFFICIENT_DEFAULT);
291module_param_named(power_efficient, wq_power_efficient, bool, 0444); 291module_param_named(power_efficient, wq_power_efficient, bool, 0444);
292 292
293bool wq_online; /* can kworkers be created yet? */
294
293static bool wq_numa_enabled; /* unbound NUMA affinity enabled */ 295static bool wq_numa_enabled; /* unbound NUMA affinity enabled */
294 296
295/* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */ 297/* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */
@@ -2583,6 +2585,9 @@ void flush_workqueue(struct workqueue_struct *wq)
2583 }; 2585 };
2584 int next_color; 2586 int next_color;
2585 2587
2588 if (WARN_ON(!wq_online))
2589 return;
2590
2586 lock_map_acquire(&wq->lockdep_map); 2591 lock_map_acquire(&wq->lockdep_map);
2587 lock_map_release(&wq->lockdep_map); 2592 lock_map_release(&wq->lockdep_map);
2588 2593
@@ -2843,6 +2848,9 @@ bool flush_work(struct work_struct *work)
2843{ 2848{
2844 struct wq_barrier barr; 2849 struct wq_barrier barr;
2845 2850
2851 if (WARN_ON(!wq_online))
2852 return false;
2853
2846 lock_map_acquire(&work->lockdep_map); 2854 lock_map_acquire(&work->lockdep_map);
2847 lock_map_release(&work->lockdep_map); 2855 lock_map_release(&work->lockdep_map);
2848 2856
@@ -2913,7 +2921,13 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork)
2913 mark_work_canceling(work); 2921 mark_work_canceling(work);
2914 local_irq_restore(flags); 2922 local_irq_restore(flags);
2915 2923
2916 flush_work(work); 2924 /*
2925 * This allows canceling during early boot. We know that @work
2926 * isn't executing.
2927 */
2928 if (wq_online)
2929 flush_work(work);
2930
2917 clear_work_data(work); 2931 clear_work_data(work);
2918 2932
2919 /* 2933 /*
@@ -3352,7 +3366,7 @@ static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs)
3352 goto fail; 3366 goto fail;
3353 3367
3354 /* create and start the initial worker */ 3368 /* create and start the initial worker */
3355 if (!create_worker(pool)) 3369 if (wq_online && !create_worker(pool))
3356 goto fail; 3370 goto fail;
3357 3371
3358 /* install */ 3372 /* install */
@@ -3417,6 +3431,7 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3417{ 3431{
3418 struct workqueue_struct *wq = pwq->wq; 3432 struct workqueue_struct *wq = pwq->wq;
3419 bool freezable = wq->flags & WQ_FREEZABLE; 3433 bool freezable = wq->flags & WQ_FREEZABLE;
3434 unsigned long flags;
3420 3435
3421 /* for @wq->saved_max_active */ 3436 /* for @wq->saved_max_active */
3422 lockdep_assert_held(&wq->mutex); 3437 lockdep_assert_held(&wq->mutex);
@@ -3425,7 +3440,8 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3425 if (!freezable && pwq->max_active == wq->saved_max_active) 3440 if (!freezable && pwq->max_active == wq->saved_max_active)
3426 return; 3441 return;
3427 3442
3428 spin_lock_irq(&pwq->pool->lock); 3443 /* this function can be called during early boot w/ irq disabled */
3444 spin_lock_irqsave(&pwq->pool->lock, flags);
3429 3445
3430 /* 3446 /*
3431 * During [un]freezing, the caller is responsible for ensuring that 3447 * During [un]freezing, the caller is responsible for ensuring that
@@ -3448,7 +3464,7 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3448 pwq->max_active = 0; 3464 pwq->max_active = 0;
3449 } 3465 }
3450 3466
3451 spin_unlock_irq(&pwq->pool->lock); 3467 spin_unlock_irqrestore(&pwq->pool->lock, flags);
3452} 3468}
3453 3469
3454/* initialize newly alloced @pwq which is associated with @wq and @pool */ 3470/* initialize newly alloced @pwq which is associated with @wq and @pool */
@@ -5457,7 +5473,17 @@ static void __init wq_numa_init(void)
5457 wq_numa_enabled = true; 5473 wq_numa_enabled = true;
5458} 5474}
5459 5475
5460static int __init init_workqueues(void) 5476/**
5477 * workqueue_init_early - early init for workqueue subsystem
5478 *
5479 * This is the first half of two-staged workqueue subsystem initialization
5480 * and invoked as soon as the bare basics - memory allocation, cpumasks and
5481 * idr are up. It sets up all the data structures and system workqueues
5482 * and allows early boot code to create workqueues and queue/cancel work
5483 * items. Actual work item execution starts only after kthreads can be
5484 * created and scheduled right before early initcalls.
5485 */
5486int __init workqueue_init_early(void)
5461{ 5487{
5462 int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL }; 5488 int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL };
5463 int i, cpu; 5489 int i, cpu;
@@ -5490,16 +5516,6 @@ static int __init init_workqueues(void)
5490 } 5516 }
5491 } 5517 }
5492 5518
5493 /* create the initial worker */
5494 for_each_online_cpu(cpu) {
5495 struct worker_pool *pool;
5496
5497 for_each_cpu_worker_pool(pool, cpu) {
5498 pool->flags &= ~POOL_DISASSOCIATED;
5499 BUG_ON(!create_worker(pool));
5500 }
5501 }
5502
5503 /* create default unbound and ordered wq attrs */ 5519 /* create default unbound and ordered wq attrs */
5504 for (i = 0; i < NR_STD_WORKER_POOLS; i++) { 5520 for (i = 0; i < NR_STD_WORKER_POOLS; i++) {
5505 struct workqueue_attrs *attrs; 5521 struct workqueue_attrs *attrs;
@@ -5536,8 +5552,36 @@ static int __init init_workqueues(void)
5536 !system_power_efficient_wq || 5552 !system_power_efficient_wq ||
5537 !system_freezable_power_efficient_wq); 5553 !system_freezable_power_efficient_wq);
5538 5554
5555 return 0;
5556}
5557
5558/**
5559 * workqueue_init - bring workqueue subsystem fully online
5560 *
5561 * This is the latter half of two-staged workqueue subsystem initialization
5562 * and invoked as soon as kthreads can be created and scheduled.
5563 * Workqueues have been created and work items queued on them, but there
5564 * are no kworkers executing the work items yet. Populate the worker pools
5565 * with the initial workers and enable future kworker creations.
5566 */
5567int __init workqueue_init(void)
5568{
5569 struct worker_pool *pool;
5570 int cpu, bkt;
5571
5572 /* create the initial workers */
5573 for_each_online_cpu(cpu) {
5574 for_each_cpu_worker_pool(pool, cpu) {
5575 pool->flags &= ~POOL_DISASSOCIATED;
5576 BUG_ON(!create_worker(pool));
5577 }
5578 }
5579
5580 hash_for_each(unbound_pool_hash, bkt, pool, hash_node)
5581 BUG_ON(!create_worker(pool));
5582
5583 wq_online = true;
5539 wq_watchdog_init(); 5584 wq_watchdog_init();
5540 5585
5541 return 0; 5586 return 0;
5542} 5587}
5543early_initcall(init_workqueues);