Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/x86/x86 cpu_proc_fork: use pcb1 and pcb2, and thus ...
details: https://anonhg.NetBSD.org/src/rev/ed4f1707cdea
branches: trunk
changeset: 748567:ed4f1707cdea
user: rmind <rmind%NetBSD.org@localhost>
date: Tue Oct 27 03:48:59 2009 +0000
description:
cpu_proc_fork: use pcb1 and pcb2, and thus make routine more readable.
Remove or update outdated comments, add new ones. Clean-up.
diffstat:
sys/arch/x86/x86/vm_machdep.c | 134 +++++++++++++++++++----------------------
1 files changed, 61 insertions(+), 73 deletions(-)
diffs (207 lines):
diff -r a380fb3f2750 -r ed4f1707cdea sys/arch/x86/x86/vm_machdep.c
--- a/sys/arch/x86/x86/vm_machdep.c Tue Oct 27 03:45:32 2009 +0000
+++ b/sys/arch/x86/x86/vm_machdep.c Tue Oct 27 03:48:59 2009 +0000
@@ -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.
+ * cpu_lwp_fork: finish a new LWP (l2) operation.
*
- * 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.
- *
- * 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) */
+
+ /* Copy the PCB from parent. */
+ memcpy(pcb2, pcb1, sizeof(struct pcb));
-#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;
+#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
Home |
Main Index |
Thread Index |
Old Index