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