On Tue, Apr 18, 2023 at 09:45:52AM -0700, Suren Baghdasaryan wrote: > On Tue, Apr 18, 2023 at 8:48 AM Peter Xu <peterx@xxxxxxxxxx> wrote: > > > > On Tue, Apr 18, 2023 at 04:32:27PM +0100, Matthew Wilcox wrote: > > > ... when we called clone()? A thread by definition has a reference to > > > its own mm. > > > > Ah yes.. thanks! > > re: I also had a quick look on do_exit() but I also didn't see where > do we e.g. wait for all the threads to stop before recycles a mm. > > We recycle mm after all refcounts are dropped in the exit path: > do_exit > exit_mm > mmput(if !mm->mm_users) > mmdrop(if !mm->mm_count) > free_mm I assume Matthew means when the task_struct is created with part of kernel_clone(). copy_mm() has: if (clone_flags & CLONE_VM) { mmget(oldmm); mm = oldmm; } else { mm = dup_mm(tsk, current->mm); if (!mm) return -ENOMEM; } If CLONE_VM, we'll mmget() on the existing mm. If !CLONE_VM, we'll just create a new one with reference held. For the latter, I think that hides in mm_init() where it'll just set it to 1: atomic_set(&mm->mm_users, 1); With mm_users>0, do_exit() will leave the mm_struct* alone since mmput() will still be called but not the final step on mmdrop(). Thanks, -- Peter Xu