On Mon, Mar 25, 2013 at 12:16 PM, Rami Rosen <roszenrami@xxxxxxxxx> 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@xxxxxxxxx> wrote: >> On Mon, Mar 25, 2013 at 1:35 AM, Rami Rosen <roszenrami@xxxxxxxxx> 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@xxxxxxxxx> 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@xxxxxxxxxxxxxxxxx >>>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies >>>> >>> >>> _______________________________________________ >>> Kernelnewbies mailing list >>> Kernelnewbies@xxxxxxxxxxxxxxxxx >>> http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies _______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies