• A
    cpu: introduce clear_tasks_mm_cpumask() helper · cb79295e
    Anton Vorontsov 提交于
    Many architectures clear tasks' mm_cpumask like this:
    
    	read_lock(&tasklist_lock);
    	for_each_process(p) {
    		if (p->mm)
    			cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
    	}
    	read_unlock(&tasklist_lock);
    
    Depending on the context, the code above may have several problems,
    such as:
    
    1. Working with task->mm w/o getting mm or grabing the task lock is
       dangerous as ->mm might disappear (exit_mm() assigns NULL under
       task_lock(), so tasklist lock is not enough).
    
    2. Checking for process->mm is not enough because process' main
       thread may exit or detach its mm via use_mm(), but other threads
       may still have a valid mm.
    
    This patch implements a small helper function that does things
    correctly, i.e.:
    
    1. We take the task's lock while whe handle its mm (we can't use
       get_task_mm()/mmput() pair as mmput() might sleep);
    
    2. To catch exited main thread case, we use find_lock_task_mm(),
       which walks up all threads and returns an appropriate task
       (with task lock held).
    
    Also, Per Peter Zijlstra's idea, now we don't grab tasklist_lock in
    the new helper, instead we take the rcu read lock. We can do this
    because the function is called after the cpu is taken down and marked
    offline, so no new tasks will get this cpu set in their mm mask.
    Signed-off-by: NAnton Vorontsov <anton.vorontsov@linaro.org>
    Cc: Richard Weinberger <richard@nod.at>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Russell King <rmk@arm.linux.org.uk>
    Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
    Cc: Mike Frysinger <vapier@gentoo.org>
    Cc: Paul Mundt <lethal@linux-sh.org>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    cb79295e
cpu.h 6.5 KB