Module Name:    src
Committed By:   rmind
Date:           Tue Oct 27 03:48:59 UTC 2009

Modified Files:
        src/sys/arch/x86/x86: vm_machdep.c

Log Message:
cpu_proc_fork: use pcb1 and pcb2, and thus make routine more readable.
Remove or update outdated comments, add new ones.  Clean-up.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/x86/x86/vm_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/x86/vm_machdep.c
diff -u src/sys/arch/x86/x86/vm_machdep.c:1.2 src/sys/arch/x86/x86/vm_machdep.c:1.3
--- src/sys/arch/x86/x86/vm_machdep.c:1.2	Wed Oct 21 21:12:04 2009
+++ src/sys/arch/x86/x86/vm_machdep.c	Tue Oct 27 03:48:59 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: vm_machdep.c,v 1.2 2009/10/21 21:12:04 rmind Exp $	*/
+/*	$NetBSD: vm_machdep.c,v 1.3 2009/10/27 03:48:59 rmind Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986 The Regents of the University of California.
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.2 2009/10/21 21:12:04 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.3 2009/10/27 03:48:59 rmind Exp $");
 
 #include "opt_mtrr.h"
 
@@ -115,8 +115,6 @@
 #endif
 #endif
 
-static void setredzone(struct lwp *);
-
 void
 cpu_proc_fork(struct proc *p1, struct proc *p2)
 {
@@ -127,97 +125,103 @@
 }
 
 /*
- * Finish a new thread operation, with LWP l2 nearly set up.
- * Copy and update the pcb and trap frame, making the child ready to run.
- *
- * Rig the child's kernel stack so that it will start out in
- * lwp_trampoline() and call child_return() with l2 as an
- * argument. This causes the newly-created child process to go
- * directly to user level with an apparent return value of 0 from
- * fork(), while the parent process returns normally.
+ * cpu_lwp_fork: finish a new LWP (l2) operation.
  *
- * l1 is the thread being forked; if l1 == &lwp0, we are creating
- * a kernel thread, and the return path and argument are specified with
- * `func' and `arg'.
+ * First LWP (l1) is the process being forked.  If it is &lwp, then we
+ * are creating a kthread, where return path and argument are specified
+ * with `func' and `arg'.
  *
  * If an alternate user-level stack is requested (with non-zero values
- * in both the stack and stacksize args), set up the user stack pointer
- * accordingly.
+ * in both the stack and stacksize arguments), then set up the user stack
+ * pointer accordingly.
  */
 void
 cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
     void (*func)(void *), void *arg)
 {
-	struct pcb *pcb = &l2->l_addr->u_pcb;
+	struct pcb *pcb1, *pcb2;
 	struct trapframe *tf;
 
+	pcb1 = &l1->l_addr->u_pcb;
+	pcb2 = &l2->l_addr->u_pcb;
+
 	/*
-	 * If fpuproc != p1, then the fpu h/w state is irrelevant and the
-	 * state had better already be in the pcb.  This is true for forks
-	 * but not for dumps.
-	 *
-	 * If fpuproc == p1, then we have to save the fpu h/w state to
-	 * p1's pcb so that we can copy it.
+	 * If parent LWP was using FPU, then we have to save the FPU h/w
+	 * state to PCB so that we can copy it.
 	 */
-	if (l1->l_addr->u_pcb.pcb_fpcpu != NULL) {
+	if (pcb1->pcb_fpcpu != NULL) {
 		fpusave_lwp(l1, true);
 	}
 
-	l2->l_md.md_flags = l1->l_md.md_flags;
-
-	/* Copy pcb from proc p1 to p2. */
+	/*
+	 * Sync the PCB before we copy it.
+	 */
 	if (l1 == curlwp) {
-		/* Sync the PCB before we copy it. */
-		savectx(curpcb);
+		KASSERT(pcb1 == curpcb);
+		savectx(pcb1);
 	} else {
 		KASSERT(l1 == &lwp0);
 	}
-	*pcb = l1->l_addr->u_pcb;
-#if defined(XEN)
-	pcb->pcb_iopl = SEL_KPL;
-#endif /* defined(XEN) */
 
-#ifdef __x86_64__
-	/*
-	 * Note: pcb_ldt_sel is handled in the pmap_activate() call when
-	 * we run the new process.
-	 */
-	pcb->pcb_rsp0 = (USER_TO_UAREA(l2->l_addr) + KSTACK_SIZE - 16) & ~0xf;
-	pcb->pcb_fs = l1->l_addr->u_pcb.pcb_fs;
-	pcb->pcb_gs = l1->l_addr->u_pcb.pcb_gs;
-#else
-	pcb->pcb_esp0 = USER_TO_UAREA(l2->l_addr) + KSTACK_SIZE - 16;
-	memcpy(&pcb->pcb_fsd, curpcb->pcb_fsd, sizeof(pcb->pcb_fsd));
-	memcpy(&pcb->pcb_gsd, curpcb->pcb_gsd, sizeof(pcb->pcb_gsd));
-	pcb->pcb_iomap = NULL;
+	/* Copy the PCB from parent. */
+	memcpy(pcb2, pcb1, sizeof(struct pcb));
+
+#if defined(XEN)
+	pcb2->pcb_iopl = SEL_KPL;
 #endif
-	l2->l_md.md_astpending = 0;
 
 	/*
-	 * Copy the trapframe.
+	 * Set the kernel stack address (from the address to uarea) and
+	 * trapframe address for child.
+	 *
+	 * Rig kernel stack so that it would start out in lwp_trampoline()
+	 * and call child_return() with l2 as an argument.  This causes the
+	 * newly-created child process to go directly to user level with a
+	 * parent return value of 0 from fork(), while the parent process
+	 * returns normally.
+	 * 
+	 * Also, copy PCB %fs/%gs base from parent.
 	 */
 #ifdef __x86_64__
-	tf = (struct trapframe *)pcb->pcb_rsp0 - 1;
+	pcb2->pcb_rsp0 = (USER_TO_UAREA(l2->l_addr) + KSTACK_SIZE - 16) & ~0xf;
+	tf = (struct trapframe *)pcb2->pcb_rsp0 - 1;
+
+	pcb2->pcb_fs = pcb1->pcb_fs;
+	pcb2->pcb_gs = pcb1->pcb_gs;
 #else
-	tf = (struct trapframe *)pcb->pcb_esp0 - 1;
+	pcb2->pcb_esp0 = (USER_TO_UAREA(l2->l_addr) + KSTACK_SIZE - 16);
+	tf = (struct trapframe *)pcb2->pcb_esp0 - 1;
+
+	memcpy(&pcb2->pcb_fsd, pcb1->pcb_fsd, sizeof(pcb2->pcb_fsd));
+	memcpy(&pcb2->pcb_gsd, pcb1->pcb_gsd, sizeof(pcb2->pcb_gsd));
+	pcb2->pcb_iomap = NULL;
 #endif
 	l2->l_md.md_regs = tf;
-	*tf = *l1->l_md.md_regs;
+
+	/* Copy the trapframe from parent. */
+	memcpy(tf, l1->l_md.md_regs, sizeof(struct trapframe));
+
+	/* Child LWP might get aston() before returning to userspace. */
 	tf->tf_trapno = T_ASTFLT;
 
-	setredzone(l2);
+#ifdef DIAGNOSTIC
+	/* Set a red zone in the kernel stack after the uarea. */
+	pmap_kremove(USER_TO_UAREA(l2->l_addr), PAGE_SIZE);
+	pmap_update(pmap_kernel());
+#endif
 
-	/*
-	 * If specified, give the child a different stack.
-	 */
+	/* If specified, set a different user stack for a child. */
 	if (stack != NULL) {
 #ifdef __x86_64__
 		tf->tf_rsp = (uint64_t)stack + stacksize;
 #else
-		tf->tf_esp = (u_int)stack + stacksize;
+		tf->tf_esp = (uint32_t)stack + stacksize;
 #endif
 	}
 
+	l2->l_md.md_flags = l1->l_md.md_flags;
+	l2->l_md.md_astpending = 0;
+
 	cpu_setfunc(l2, func, arg);
 }
 
@@ -278,22 +282,6 @@
 }
 
 /*
- * Set a red zone in the kernel stack after the u. area.
- */
-static void
-setredzone(struct lwp *l)
-{
-
-#ifdef DIAGNOSTIC
-	vaddr_t addr;
-
-	addr = USER_TO_UAREA(l->l_addr);
-	pmap_kremove(addr, PAGE_SIZE);
-	pmap_update(pmap_kernel());
-#endif
-}
-
-/*
  * Convert kernel VA to physical address
  */
 paddr_t

Reply via email to