• Tejun Heo's avatar
    workqueue: make workqueue available early during boot · 3347fa09
    Tejun Heo authored
    
    
    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: default avatarTejun Heo <tj@kernel.org>
    Suggested-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Link: http://lkml.kernel.org/r/CA+55aFx0vPuMuxn00rBSM192n-Du5uxy+4AvKa0SBSOVJeuCGg@mail.gmail.com
    3347fa09
workqueue.c 154 KB