summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2017-02-12 04:55:09 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2017-02-12 04:55:09 +0000
commit89043ff36c6d6b7d281d035919b813f9866d1e68 (patch)
tree876e1797e6617d45dc347d704757015e0635dd5b /sys/arch
parent68a5515f6186c6c1d00d6abe9453463fbdc66c99 (diff)
Split up fork1():
- FORK_THREAD handling is a totally separate function, thread_fork(), that is only used by sys___tfork() and which loses the flags, func, arg, and newprocp parameters and gains tcb parameter to guarantee the new thread's TCB is set before the creating thread returns - fork1() loses its stack and tidptr parameters Common bits factor out: - struct proc allocation and initialization moves to thread_new() - maxthread handling moves to fork_check_maxthread() - setting the new thread running moves to fork_thread_start() The MD cpu_fork() function swaps its unused stacksize parameter for a tcb parameter. luna88k testing by aoyama@, alpha testing by dlg@ ok mpi@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/alpha/alpha/vm_machdep.c33
-rw-r--r--sys/arch/amd64/amd64/vm_machdep.c12
-rw-r--r--sys/arch/arm/arm/vm_machdep.c38
-rw-r--r--sys/arch/arm64/arm64/vm_machdep.c10
-rw-r--r--sys/arch/hppa/hppa/vm_machdep.c8
-rw-r--r--sys/arch/i386/i386/vm_machdep.c13
-rw-r--r--sys/arch/m88k/m88k/vm_machdep.c19
-rw-r--r--sys/arch/mips64/mips64/vm_machdep.c16
-rw-r--r--sys/arch/powerpc/powerpc/vm_machdep.c10
-rw-r--r--sys/arch/sh/sh/vm_machdep.c29
-rw-r--r--sys/arch/sparc64/sparc64/vm_machdep.c34
11 files changed, 106 insertions, 116 deletions
diff --git a/sys/arch/alpha/alpha/vm_machdep.c b/sys/arch/alpha/alpha/vm_machdep.c
index 7ff834b9ec4..48f6ec11f2a 100644
--- a/sys/arch/alpha/alpha/vm_machdep.c
+++ b/sys/arch/alpha/alpha/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.45 2016/10/04 05:55:09 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.46 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.55 2000/03/29 03:49:48 simonb Exp $ */
/*
@@ -71,24 +71,19 @@ cpu_exit(p)
* 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
- * switch_trampoline() and call child_return() with p2 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.
+ * proc_trampoline() and call 'func' with 'arg' as an argument.
+ * For normal processes this is child_return(), which causes the
+ * child to go directly to user level with an apparent return value
+ * of 0 from fork(), while the parent process returns normally.
+ * For kernel threads this will be a function that never return.
*
- * p1 is the process being forked;
- *
- * If an alternate user-level stack is requested (with non-NULL stack arg),
- * set up the user stack pointer
- * accordingly.
+ * An alternate user-level stack or TCB can be requested by passing
+ * a non-NULL value; these are poked into the PCB so they're in
+ * effect at the initial return to userspace.
*/
void
-cpu_fork(p1, p2, stack, stacksize, func, arg)
- struct proc *p1, *p2;
- void *stack;
- size_t stacksize;
- void (*func)(void *);
- void *arg;
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
+ void (*func)(void *), void *arg)
{
struct user *up = p2->p_addr;
@@ -115,15 +110,17 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
/*
* Copy pcb and stack from proc p1 to p2.
- * If specified, give the child a different stack.
+ * If specified, give the child a different stack and/or TCB.
* We do this as cheaply as possible, copying only the active
* part of the stack. The stack and pcb need to agree;
*/
up->u_pcb = p1->p_addr->u_pcb;
if (stack != NULL)
- up->u_pcb.pcb_hw.apcb_usp = (u_long)stack + stacksize;
+ up->u_pcb.pcb_hw.apcb_usp = (u_long)stack;
else
up->u_pcb.pcb_hw.apcb_usp = alpha_pal_rdusp();
+ if (tcb != NULL)
+ up->u_pcb.pcb_hw.apcb_unique = (unsigned long)tcb;
/*
* Arrange for a non-local goto when the new process
diff --git a/sys/arch/amd64/amd64/vm_machdep.c b/sys/arch/amd64/amd64/vm_machdep.c
index 2b402e5ec74..42dc47f92ea 100644
--- a/sys/arch/amd64/amd64/vm_machdep.c
+++ b/sys/arch/amd64/amd64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.35 2016/04/03 19:49:35 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.36 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */
/*-
@@ -66,10 +66,10 @@ void setredzone(struct proc *);
* Finish a fork operation, with process p2 nearly set up.
* Copy and update the kernel stack and pcb, making the child
* ready to run, and marking it so that it can return differently
- * than the parent. Returns 1 in the child process, 0 in the parent.
+ * than the parent.
*/
void
-cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
void (*func)(void *), void *arg)
{
struct pcb *pcb = &p2->p_addr->u_pcb;
@@ -112,10 +112,12 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
setredzone(p2);
/*
- * If specified, give the child a different stack.
+ * If specified, give the child a different stack and/or TCB
*/
if (stack != NULL)
- tf->tf_rsp = (u_int64_t)stack + stacksize;
+ tf->tf_rsp = (u_int64_t)stack;
+ if (tcb != NULL)
+ pcb->pcb_fsbase = (u_int64_t)tcb;
sf = (struct switchframe *)tf - 1;
sf->sf_r12 = (u_int64_t)func;
diff --git a/sys/arch/arm/arm/vm_machdep.c b/sys/arch/arm/arm/vm_machdep.c
index 38dba6d7d77..9b2a00a92f5 100644
--- a/sys/arch/arm/arm/vm_machdep.c
+++ b/sys/arch/arm/arm/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.18 2016/07/31 09:18:01 jsg Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.19 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.31 2004/01/04 11:33:29 jdolecek Exp $ */
/*
@@ -80,24 +80,21 @@ extern void proc_trampoline (void);
/*
* Finish a fork operation, with process p2 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
- * proc_trampoline() and call child_return() with p2 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.
*
- * p1 is the process being forked; if p1 == &proc0, we are creating
- * a kernel thread, and the return path and argument are specified with
- * `func' and `arg'.
+ * Rig the child's kernel stack so that it will start out in
+ * proc_trampoline() and call 'func' with 'arg' as an argument.
+ * For normal processes this is child_return(), which causes the
+ * child to go directly to user level with an apparent return value
+ * of 0 from fork(), while the parent process returns normally.
+ * For kernel threads this will be a function that never return.
*
- * 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.
+ * An alternate user-level stack or TCB can be requested by passing
+ * a non-NULL value; these are poked into the PCB so they're in
+ * effect at the initial return to userspace.
*/
void
-cpu_fork(struct proc *p1, struct proc *p2, void *stack,
- size_t stacksize, void (*func) (void *), void *arg)
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
+ void (*func)(void *), void *arg)
{
struct pcb *pcb = (struct pcb *)&p2->p_addr->u_pcb;
struct trapframe *tf;
@@ -130,16 +127,17 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack,
pmap_activate(p2);
- p2->p_addr->u_pcb.pcb_tf = tf =
- (struct trapframe *)pcb->pcb_un.un_32.pcb32_sp - 1;
+ pcb->pcb_tf = tf = (struct trapframe *)pcb->pcb_un.un_32.pcb32_sp - 1;
*tf = *p1->p_addr->u_pcb.pcb_tf;
/*
- * If specified, give the child a different stack (make sure
- * it's 8-byte aligned).
+ * If specified, give the child a different stack and/or TCB.
+ * Enforce 8-byte alignment on the stack.
*/
if (stack != NULL)
- tf->tf_usr_sp = ((vaddr_t)(stack) + stacksize) & -8;
+ tf->tf_usr_sp = (vaddr_t)stack & -8;
+ if (tcb != NULL)
+ p2->p_addr->u_pcb.pcb_tcb = tcb;
sf = (struct switchframe *)tf - 1;
sf->sf_r4 = (u_int)func;
diff --git a/sys/arch/arm64/arm64/vm_machdep.c b/sys/arch/arm64/arm64/vm_machdep.c
index c2e42e53234..3a879b9dc26 100644
--- a/sys/arch/arm64/arm64/vm_machdep.c
+++ b/sys/arch/arm64/arm64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.1 2016/12/17 23:38:33 patrick Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.2 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */
/*-
@@ -66,7 +66,7 @@
* than the parent. Returns 1 in the child process, 0 in the parent.
*/
void
-cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
void (*func)(void *), void *arg)
{
struct pcb *pcb = (struct pcb *)&p2->p_addr->u_pcb;
@@ -86,11 +86,13 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
- 0x10);
tf = (struct trapframe *)STACKALIGN(tf);
- p2->p_addr->u_pcb.pcb_tf = tf;
+ pcb->pcb_tf = tf;
*tf = *p1->p_addr->u_pcb.pcb_tf;
if (stack != NULL)
- tf->tf_sp = STACKALIGN((u_int)(stack) + stacksize);
+ tf->tf_sp = STACKALIGN((u_int)(stack));
+ if (tcb != NULL)
+ pcb->pcb_tcb = tcb;
sf = (struct switchframe *)tf - 1;
sf->sf_x19 = (uint64_t)func;
diff --git a/sys/arch/hppa/hppa/vm_machdep.c b/sys/arch/hppa/hppa/vm_machdep.c
index 11bceafc94c..eb517d2def7 100644
--- a/sys/arch/hppa/hppa/vm_machdep.c
+++ b/sys/arch/hppa/hppa/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.81 2015/05/05 02:13:46 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.82 2017/02/12 04:55:08 guenther Exp $ */
/*
* Copyright (c) 1999-2004 Michael Shalayeff
@@ -49,7 +49,7 @@
extern struct pool hppa_fppl;
void
-cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
void (*func)(void *), void *arg)
{
struct pcb *pcbp;
@@ -102,10 +102,12 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
(curcpu()->ci_psw & PSL_O);
/*
- * If specified, give the child a different stack.
+ * If specified, give the child a different stack and/or TCB
*/
if (stack != NULL)
setstack(tf, (u_long)stack, 0); /* XXX ignore error? */
+ if (tcb != NULL)
+ tf->tf_cr27 = (u_long)tcb;
/*
* Build stack frames for the cpu_switchto & co.
diff --git a/sys/arch/i386/i386/vm_machdep.c b/sys/arch/i386/i386/vm_machdep.c
index 49901d20f3e..182795c274f 100644
--- a/sys/arch/i386/i386/vm_machdep.c
+++ b/sys/arch/i386/i386/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.64 2016/04/03 17:45:30 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.65 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.61 1996/05/03 19:42:35 christos Exp $ */
/*-
@@ -67,12 +67,9 @@
* Copy and update the kernel stack and pcb, making the child
* ready to run, and marking it so that it can return differently
* than the parent. Returns 1 in the child process, 0 in the parent.
- * We currently double-map the user area so that the stack is at the same
- * address in each process; in the future we will probably relocate
- * the frame pointers on the stack after copying.
*/
void
-cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
void (*func)(void *), void *arg)
{
struct pcb *pcb = &p2->p_addr->u_pcb;
@@ -104,10 +101,12 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
*tf = *p1->p_md.md_regs;
/*
- * If specified, give the child a different stack.
+ * If specified, give the child a different stack and/or TCB
*/
if (stack != NULL)
- tf->tf_esp = (u_int)stack + stacksize;
+ tf->tf_esp = (u_int)stack;
+ if (tcb != NULL)
+ i386_set_threadbase(p2, (uint32_t)tcb, TSEG_GS);
sf = (struct switchframe *)tf - 1;
sf->sf_esi = (int)func;
diff --git a/sys/arch/m88k/m88k/vm_machdep.c b/sys/arch/m88k/m88k/vm_machdep.c
index d4cb331f49b..c247482c54f 100644
--- a/sys/arch/m88k/m88k/vm_machdep.c
+++ b/sys/arch/m88k/m88k/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.24 2015/05/05 02:13:47 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.25 2017/02/12 04:55:08 guenther Exp $ */
/*
* Copyright (c) 1998 Steve Murphree, Jr.
@@ -67,18 +67,11 @@ extern void switch_exit(struct proc *);
* Copy and update the kernel stack and pcb, making the child
* ready to run, and marking it so that it can return differently
* than the parent. Returns 1 in the child process, 0 in the parent.
- * We currently double-map the user area so that the stack is at the same
- * address in each process; in the future we will probably relocate
- * the frame pointers on the stack after copying.
*/
void
-cpu_fork(p1, p2, stack, stacksize, func, arg)
- struct proc *p1, *p2;
- void *stack;
- size_t stacksize;
- void (*func)(void *);
- void *arg;
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
+ void (*func)(void *), void *arg)
{
struct ksigframe {
void (*func)(void *);
@@ -100,10 +93,12 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
p2->p_md.md_tf = (struct trapframe *)USER_REGS(p2);
/*
- * If specified, give the child a different stack.
+ * If specified, give the child a different stack and/or TCB.
*/
if (stack != NULL)
- USER_REGS(p2)->r[31] = (u_int)stack + stacksize;
+ USER_REGS(p2)->r[31] = (u_int)stack;
+ if (tcb != NULL)
+ USER_REGS(p2)->r[27] = (u_int)tcb;
ksfp = (struct ksigframe *)((char *)p2->p_addr + USPACE) - 1;
ksfp->func = func;
diff --git a/sys/arch/mips64/mips64/vm_machdep.c b/sys/arch/mips64/mips64/vm_machdep.c
index f49bed30773..366d7c6969a 100644
--- a/sys/arch/mips64/mips64/vm_machdep.c
+++ b/sys/arch/mips64/mips64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.33 2016/03/06 19:42:27 mpi Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.34 2017/02/12 04:55:08 guenther Exp $ */
/*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1992, 1993
@@ -61,12 +61,8 @@ extern void proc_trampoline(void);
* Finish a fork operation, with process p2 nearly set up.
*/
void
-cpu_fork(p1, p2, stack, stacksize, func, arg)
- struct proc *p1, *p2;
- void *stack;
- size_t stacksize;
- void (*func)(void *);
- void *arg;
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
+ void (*func)(void *), void *arg)
{
struct cpu_info *ci = curcpu();
struct pcb *pcb;
@@ -117,10 +113,12 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
p2->p_md.md_regs = &p2->p_addr->u_pcb.pcb_regs;
/*
- * If specified, give the child a different stack.
+ * If specified, give the child a different stack and/or TCB.
*/
if (stack != NULL)
- p2->p_md.md_regs->sp = (u_int64_t)stack + stacksize;
+ p2->p_md.md_regs->sp = (u_int64_t)stack;
+ if (tcb != NULL)
+ TCB_SET(p2, tcb);
/*
* Copy the process control block to the new proc and
diff --git a/sys/arch/powerpc/powerpc/vm_machdep.c b/sys/arch/powerpc/powerpc/vm_machdep.c
index 43e18f7401e..fc64451a15c 100644
--- a/sys/arch/powerpc/powerpc/vm_machdep.c
+++ b/sys/arch/powerpc/powerpc/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.48 2015/05/05 02:13:47 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.49 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.1 1996/09/30 16:34:57 ws Exp $ */
/*
@@ -49,7 +49,7 @@
* Finish a fork operation, with process p2 nearly set up.
*/
void
-cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
void (*func)(void *), void *arg)
{
struct trapframe *tf;
@@ -92,7 +92,11 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
*/
if (stack != NULL) {
tf = trapframe(p2);
- tf->fixreg[1] = (register_t)stack + stacksize;
+ tf->fixreg[1] = (register_t)stack;
+ }
+ if (tcb != NULL) {
+ tf = trapframe(p2);
+ tf->fixreg[2] = (register_t)tcb;
}
stktop2 = (caddr_t)((u_long)stktop2 & ~15); /* Align stack pointer */
diff --git a/sys/arch/sh/sh/vm_machdep.c b/sys/arch/sh/sh/vm_machdep.c
index 77b50487b5b..16645ebfd0d 100644
--- a/sys/arch/sh/sh/vm_machdep.c
+++ b/sys/arch/sh/sh/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.13 2015/05/05 02:13:47 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.14 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.53 2006/08/31 16:49:21 matt Exp $ */
/*
@@ -120,23 +120,20 @@ extern void proc_trampoline(void);
/*
* Finish a fork operation, with process p2 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
- * proc_trampoline() and call child_return() with p2 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.
- *
- * p1 is the process being forked; if p1 == &proc0, we are creating
- * a kernel thread, and the return path and argument are specified with
- * `func' and `arg'.
+ * proc_trampoline() and call 'func' with 'arg' as an argument.
+ * For normal processes this is child_return(), which causes the
+ * child to go directly to user level with an apparent return value
+ * of 0 from fork(), while the parent process returns normally.
+ * For kernel threads this will be a function that never return.
*
- * 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.
+ * An alternate user-level stack or TCB can be requested by passing
+ * a non-NULL value; these are poked into the PCB so they're in
+ * effect at the initial return to userspace.
*/
void
-cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
void (*func)(void *), void *arg)
{
struct pcb *pcb;
@@ -213,7 +210,9 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
* If specified, give the child a different stack.
*/
if (stack != NULL)
- tf->tf_r15 = (u_int)stack + stacksize;
+ tf->tf_r15 = (int)stack;
+ if (tcb != NULL)
+ tf->tf_gbr = (int)tcb;
/* Setup switch frame */
sf = &pcb->pcb_sf;
diff --git a/sys/arch/sparc64/sparc64/vm_machdep.c b/sys/arch/sparc64/sparc64/vm_machdep.c
index c30e79a42a7..18e012ed879 100644
--- a/sys/arch/sparc64/sparc64/vm_machdep.c
+++ b/sys/arch/sparc64/sparc64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.35 2015/11/06 06:33:26 guenther Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.36 2017/02/12 04:55:08 guenther Exp $ */
/* $NetBSD: vm_machdep.c,v 1.38 2001/06/30 00:02:20 eeh Exp $ */
/*
@@ -153,26 +153,19 @@ char cpu_forkname[] = "cpu_fork()";
* 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
- * proc_trampoline() and call child_return() with p2 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.
+ * proc_trampoline() and call 'func' with 'arg' as an argument.
+ * For normal processes this is child_return(), which causes the
+ * child to go directly to user level with an apparent return value
+ * of 0 from fork(), while the parent process returns normally.
+ * For kernel threads this will be a function that never return.
*
- * p1 is the process being forked; if p1 == &proc0, we are creating
- * a kernel thread, and the 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.
+ * An alternate user-level stack or TCB can be requested by passing
+ * a non-NULL value; these are poked into the PCB so they're in
+ * effect at the initial return to userspace.
*/
void
-cpu_fork(p1, p2, stack, stacksize, func, arg)
- struct proc *p1, *p2;
- void *stack;
- size_t stacksize;
- void (*func)(void *);
- void *arg;
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
+ void (*func)(void *), void *arg)
{
struct pcb *opcb = &p1->p_addr->u_pcb;
struct pcb *npcb = &p2->p_addr->u_pcb;
@@ -240,10 +233,11 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
* with space reserved for the frame, and zero the frame pointer.
*/
if (stack != NULL) {
- tf2->tf_out[6] = (u_int64_t)(u_long)stack + stacksize
- - (BIAS + CC64FSZ);
+ tf2->tf_out[6] = (u_int64_t)(u_long)stack - (BIAS + CC64FSZ);
tf2->tf_in[6] = 0;
}
+ if (tcb != NULL)
+ tf2->tf_global[7] = (u_int64_t)tcb;
/* Construct kernel frame to return to in cpu_switch() */
rp = (struct rwindow *)((u_long)npcb + TOPFRAMEOFF);