Thread (6 messages) 6 messages, 3 authors, 2013-03-25

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

From: anish singh <hidden>
Date: 2013-03-25 06:02:18

On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen [off-list ref] 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 [off-list ref] wrote:
quoted
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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help