All of lore.kernel.org
 help / color / mirror / Atom feed
* Why we Use both mm_users and mm_count in struct mm_struct{ }
@ 2013-03-23  5:02 Niroj Pokhrel
  2013-03-24 20:05 ` Rami Rosen
  0 siblings, 1 reply; 6+ messages in thread
From: Niroj Pokhrel @ 2013-03-23  5:02 UTC (permalink / raw)
  To: kernelnewbies

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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20130323/c04e3ebf/attachment.html 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Why we Use both mm_users and mm_count in struct mm_struct{ }
  2013-03-23  5:02 Why we Use both mm_users and mm_count in struct mm_struct{ } Niroj Pokhrel
@ 2013-03-24 20:05 ` Rami Rosen
  2013-03-25  6:02   ` anish singh
  0 siblings, 1 reply; 6+ messages in thread
From: Rami Rosen @ 2013-03-24 20:05 UTC (permalink / raw)
  To: kernelnewbies

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@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
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Why we Use both mm_users and mm_count in struct mm_struct{ }
  2013-03-24 20:05 ` Rami Rosen
@ 2013-03-25  6:02   ` anish singh
  2013-03-25  6:32     ` Niroj Pokhrel
  2013-03-25  6:46     ` Rami Rosen
  0 siblings, 2 replies; 6+ messages in thread
From: anish singh @ 2013-03-25  6:02 UTC (permalink / raw)
  To: kernelnewbies

On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen <roszenrami@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@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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Why we Use both mm_users and mm_count in struct mm_struct{ }
  2013-03-25  6:02   ` anish singh
@ 2013-03-25  6:32     ` Niroj Pokhrel
  2013-03-25  6:46     ` Rami Rosen
  1 sibling, 0 replies; 6+ messages in thread
From: Niroj Pokhrel @ 2013-03-25  6:32 UTC (permalink / raw)
  To: kernelnewbies

On Mon, Mar 25, 2013 at 11:32 AM, anish singh
<anish198519851985@gmail.com>wrote:

> On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen <roszenrami@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@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
>

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 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Why we Use both mm_users and mm_count in struct mm_struct{ }
  2013-03-25  6:02   ` anish singh
  2013-03-25  6:32     ` Niroj Pokhrel
@ 2013-03-25  6:46     ` Rami Rosen
  2013-03-25  7:13       ` anish singh
  1 sibling, 1 reply; 6+ messages in thread
From: Rami Rosen @ 2013-03-25  6:46 UTC (permalink / raw)
  To: kernelnewbies

Hi,

Regarding your question about the previous thread:
Think of a context switch, let's say between a userspace process and a
kernel thread. A context switch is done between two processes
(processes are represented by struct task_struct). So when you look at
context_switch() prototype, you see:

context_switch(struct rq *rq, struct task_struct *prev,
...)

and prev is the process which ran in the run_queue of the scheduler
previously, before switching
to the new kernel thread. And we borrow memory descriptor from this process.

Rgs,
Rami Rosen
http://ramirose.wix.com/ramirosen






On Mon, Mar 25, 2013 at 8:02 AM, anish singh
<anish198519851985@gmail.com> wrote:
> On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen <roszenrami@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@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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Why we Use both mm_users and mm_count in struct mm_struct{ }
  2013-03-25  6:46     ` Rami Rosen
@ 2013-03-25  7:13       ` anish singh
  0 siblings, 0 replies; 6+ messages in thread
From: anish singh @ 2013-03-25  7:13 UTC (permalink / raw)
  To: kernelnewbies

On Mon, Mar 25, 2013 at 12:16 PM, Rami Rosen <roszenrami@gmail.com> wrote:
> Hi,
>
> Regarding your question about the previous thread:
> Think of a context switch, let's say between a userspace process and a
> kernel thread. A context switch is done between two processes
> (processes are represented by struct task_struct). So when you look at
> context_switch() prototype, you see:
>
> context_switch(struct rq *rq, struct task_struct *prev,
> ...)
>
> and prev is the process which ran in the run_queue of the scheduler
> previously, before switching
> to the new kernel thread. And we borrow memory descriptor from this process.
and I think the memory descriptor would be changed so that it can point
to the kernel thread.
>
> Rgs,
> Rami Rosen
> http://ramirose.wix.com/ramirosen
>
>
>
>
>
>
> On Mon, Mar 25, 2013 at 8:02 AM, anish singh
> <anish198519851985@gmail.com> wrote:
>> On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen <roszenrami@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@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

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-03-25  7:13 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-23  5:02 Why we Use both mm_users and mm_count in struct mm_struct{ } Niroj Pokhrel
2013-03-24 20:05 ` Rami Rosen
2013-03-25  6:02   ` anish singh
2013-03-25  6:32     ` Niroj Pokhrel
2013-03-25  6:46     ` Rami Rosen
2013-03-25  7:13       ` anish singh

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.