Hi, Niroj, Please look at the following scenario: Suppose we create a kernel thread. With kernel threads, the mm member of the task_struct is NULL. (We are not permitted to access user space addresses from kernel thread, so we don't need mm). Kernel threads use ("borrow") the active_mm of the previous thread. But in order to avoid freeing the active_mm if the previous threads terminates before the kernel thread terminates, we increment mm_count of the active_mm of the previous thread when we create a kernel thread (which "borrows" the active_mm of the previous thread). In such a case, even if the mm_users is 0, mm_count is not 0, and we do not free that mm_active. (remember that mm_users is initialized to 1). To be more specific: when that previous thread terminates, we call the mmput() (see exit_mm(), in kernel/exit.c) mmput() decrements mm_users and calls mmdrop(). Since in mmdrop(), after decrements mm_count it is not 0, we do not free the mm_struct. Here are the code snippets: /* * Decrement the use count and release all resources for an mm. */ void mmput(struct mm_struct *mm) { might_sleep(); if (atomic_dec_and_test(&mm->mm_users)) { uprobe_clear_state(mm); exit_aio(mm); ksm_exit(mm); khugepaged_exit(mm); /* must run before exit_mmap */ exit_mmap(mm); set_mm_exe_file(mm, NULL); if (!list_empty(&mm->mmlist)) { spin_lock(&mmlist_lock); list_del(&mm->mmlist); spin_unlock(&mmlist_lock); } if (mm->binfmt) module_put(mm->binfmt->module); mmdrop(mm); } } mmdrop() is for freeing a memory descriptor: static inline void mmdrop(struct mm_struct * mm) { if (unlikely(atomic_dec_and_test(&mm->mm_count))) __mmdrop(mm); } When the condition if (!mm) is true, this means this is a kernel thread: static inline void context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next) { struct mm_struct *mm, *oldmm; prepare_task_switch(rq, prev, next); mm = next->mm; oldmm = prev->active_mm; /* * For paravirt, this is coupled with an exit in switch_to to * combine the page table reload and the switch backend into * one hypercall. */ arch_start_context_switch(prev); if (!mm) { next->active_mm = oldmm; atomic_inc(&oldmm->mm_count); enter_lazy_tlb(oldmm, next); } else ... Regards, Rami Rosen http://ramirose.wix.com/ramirosen On Sat, Mar 23, 2013 at 7:02 AM, Niroj Pokhrel <nirojpokhrel@xxxxxxxxx> wrote: > Hi all, > I have been going through the Address Space in the linux and came across two > variables in the struct mm_struct and I'm a bit confused about the two: > struct mm_struct > { > .......... > atomic_t mm_users; > atomic_t mm_count; > ............ > } > Basically, after reading through I came to understand that mm_users are used > to store the number of processes or threads using the memory so depending > upon the number of users it is going to be set. > But, I am confused with mm_count, it is said the mm_count is increment by > one for all the mm_users and when all the mm_users value is reduced to zero > then mm_count is reduced. So, my question is can the value of mm_count be > ever greater than one because all the mm_users are equivalent to mm_count . > So, if not then why are we using the mm_count as we can simply remove the > memory areas whenever the mm_users count reduce to zero. > May be the explanation is simple but I'm lost. Thanking all of you in > advance. > > > Regards, > Niroj Pokhrel > > _______________________________________________ > Kernelnewbies mailing list > Kernelnewbies@xxxxxxxxxxxxxxxxx > http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies > _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies