Why we Use both mm_users and mm_count in struct mm_struct{ }

anish singh anish198519851985 at gmail.com
Mon Mar 25 02:02:18 EDT 2013


On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen <roszenrami at gmail.com> wrote:
> 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.
as we know that kernel threads are not associated with any user space
process then why this overheads of active_mm or why we borrow the
active_mm of the previous thread.
Can you explain: what is previous thread here?
> 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 at gmail.com> 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 at kernelnewbies.org
>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
>>
>
> _______________________________________________
> Kernelnewbies mailing list
> Kernelnewbies at kernelnewbies.org
> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies



More information about the Kernelnewbies mailing list