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

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

From: Niroj Pokhrel <hidden>
Date: 2013-03-25 06:32:17

On Mon, Mar 25, 2013 at 11:32 AM, anish singh
[off-list ref]wrote:
On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen [off-list ref] wrote:
quoted
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?
quoted
But in order to avoid freeing the active_mm if the previous threads
terminates
quoted
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
quoted
Hi all,
I have been going through the Address Space in the linux and came
across two
quoted
quoted
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
quoted
quoted
to store the number of processes or threads using the memory so
depending
quoted
quoted
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
quoted
quoted
one for all the mm_users and when all the mm_users value is reduced to
zero
quoted
quoted
then mm_count is reduced. So, my question is can the value of mm_count
be
quoted
quoted
ever greater than one because all the mm_users are equivalent to
mm_count .
quoted
quoted
So, if not then why are we using the mm_count as we can simply remove
the
quoted
quoted
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
Hi Anish,

The kernel_thread doesn't have user context so it basically has its mm
space pointing to NULL. So, if any kernel threads has preempted the kernel
then it still needs page table entries to access the kernel memory space
but since its mm space is pointing to the NULL it wouldn't have luxury. So,
how does kernel gets that entry then ?? It basically uses the page table
entry of the process which it preempted ( this is the previous thread as
mentioned in the answer by Rami). So, when it starts using this thread then
mm_count (primary reference) of that memory is increased by 1.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20130325/ceebea9c/attachment-0001.html 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help