• Andrew Morton's avatar
    [PATCH] kthread primitive · 933ba102
    Andrew Morton authored
    From: Rusty Russell <rusty@rustcorp.com.au>
    
    These two patches provide the framework for stopping kernel threads to
    allow hotplug CPU.  This one just adds kthread.c and kthread.h, next
    one uses it.
    
    Most importantly, adds a Monty Python quote to the kernel.
    
    Details:
    
    The hotplug CPU code introduces two major problems:
    
    1) Threads which previously never stopped (migration thread,
       ksoftirqd, keventd) have to be stopped cleanly as CPUs go offline.
    2) Threads which previously never had to be created now have
       to be created when a CPU goes online.
    
    Unfortunately, stopping a thread is fairly baroque, involving memory
    barriers, a completion and spinning until the task is actually dead
    (for example, complete_and_exit() must be used if inside a module).
    
    There are also three problems in starting a thread:
    1) Doing it from a random process context risks environment contamination:
       better to do it from keventd to guarantee a clean environment, a-la
       call_usermodehelper.
    2) Getting the task struct without races is a hard: see kernel/sched.c
       migration_call(), kernel/workqueue.c create_workqueue_thread().
    3) There are races in starting a thread for a CPU which is not yet
       online: migration thread does a complex dance at the moment for
       a similar reason (there may be no migration thread to migrate us).
    
    Place all this logic in some primitives to make life easier:
    kthread_create() and kthread_stop().  These primitives require no
    extra data-structures in the caller: they operate on normal "struct
    task_struct"s.
    
    Other changes:
    
    - Expose keventd_up(), as keventd and migration threads will use kthread to
      launch, and kthread normally uses workqueues and must recognize this case.
    
    - Kthreads created at boot before "keventd" are spawned directly.  However,
      this means that they don't have all signals blocked, and hence can be
      killed.  The simplest solution is to always explicitly block all signals in
      the kthread.
    
    - Change over the migration threads, the workqueue threads and the
      ksoftirqd threads to use kthread.
    
    - module.c currently spawns threads directly to stop the machine, so a
      module can be atomically tested for removal.
    
    - Unfortunately, this means that the current task is manipulated (which
      races with set_cpus_allowed, for example), and it can't set its priority
      artificially high.  Using a kernel thread can solve this cleanly, and with
      kthread_run, it's simple.
    
    - kthreads use keventd, so they inherit its cpus_allowed mask.  Unset it.
      All current users set it explicity anyway, but it's nice to fix.
    
    - call_usermode_helper uses keventd, so the process created inherits its
      cpus_allowed mask.  Unset it.
    
    - Prevent errors in boot when cpus_possible() contains a cpu which is not
      online (ie.  a cpu didn't come up).  This doesn't happen on x86, since a
      boot failure makes that CPU no longer possible (hacky, but it works).
    
    - When the cpu fails to come up, some callbacks do kthread_stop(), which
      doesn't work without keventd (which hasn't started yet).  Call it directly,
      and take care that it restores signal state (note: do_sigaction does a
      flush on blocked signals, so we don't need to repeat it).
    933ba102
workqueue.c 8.44 KB