On Tue, Nov 8, 2011 at 8:47 AM, Ralf Baechle <ralf@xxxxxxxxxxxxxx> wrote: > On Sat, Nov 05, 2011 at 02:21:10PM -0700, Kevin Cernekee wrote: > >> +void local_flush_tlb_all_mm(void) >> +{ >> + struct task_struct *p; >> + >> + for_each_process(p) >> + if (p->mm) >> + local_flush_tlb_mm(p->mm); > > Aside of for_each_process being a potencially very heavy iterator - there > can be thousands of threads on some systems, even embedded systems I'm This is called from play_dead() on a CPU that has been hot-unplugged. FWIW for_each_process() is also called from check_for_tasks() when bringing down a CPU. I wonder if that would be a better place to add a hook to drop the MMU contexts, ala: diff --git a/kernel/cpu.c b/kernel/cpu.c index 563f136..5854401 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -184,6 +184,7 @@ static inline void check_for_tasks(int cpu) "(state = %ld, flags = %x)\n", p->comm, task_pid_nr(p), cpu, p->state, p->flags); + arch_drop_mmu_context(p, cpu); } write_unlock_irq(&tasklist_lock); } But it does run on a "surviving" CPU, not the dying CPU, so I'm not positive it would work the same way. > missing the task_list lock being taken so bad things could happen. Right, so without acquiring tasklist_lock, somebody else could rearrange the list while I'm iterating through it. Do I need to call task_lock(p) before touching p->mm, or would acquiring a write lock on tasklist_lock be sufficient?