From: claudio Date: Mon, 19 Feb 2024 09:59:29 +0000 (+0000) Subject: In cpu_fork() do not copy the register windows stashed in the u_pcb X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=4930177a55dbfa846ec36a56eaa025fd8a8cf8d2;p=openbsd In cpu_fork() do not copy the register windows stashed in the u_pcb if the new proc has its own stack. In that case the new thread starts with a fresh stack and there are no register windows to spill back. This fixes the pthread issues that kurt@ was struggling with for a long time. Depending on the scheduler a thread would stomp over another threads stack which caused strange crashes. Improved diff provided by miod@ OK miod@ mpi@ kurt@ --- diff --git a/sys/arch/sparc64/sparc64/vm_machdep.c b/sys/arch/sparc64/sparc64/vm_machdep.c index 4a7ecb9a2fc..c5016aed0fd 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.42 2022/10/25 06:05:57 guenther Exp $ */ +/* $OpenBSD: vm_machdep.c,v 1.43 2024/02/19 09:59:29 claudio Exp $ */ /* $NetBSD: vm_machdep.c,v 1.38 2001/06/30 00:02:20 eeh Exp $ */ /* @@ -100,6 +100,7 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb, struct pcb *npcb = &p2->p_addr->u_pcb; struct trapframe *tf2; struct rwindow *rp; + size_t pcbsz; extern struct proc proc0; /* @@ -136,7 +137,15 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb, #else opcb->lastcall = NULL; #endif - bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb)); + /* + * If a new stack is provided, do not bother copying saved windows + * in the new pcb. Also, we'll reset pcb_nsaved accordingly below. + */ + if (stack != NULL) + pcbsz = offsetof(struct pcb, pcb_rw); + else + pcbsz = sizeof(struct pcb); + bcopy((caddr_t)opcb, (caddr_t)npcb, pcbsz); if (p1->p_md.md_fpstate) { fpusave_proc(p1, 1); p2->p_md.md_fpstate = malloc(sizeof(struct fpstate), @@ -162,6 +171,7 @@ cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb, * with space reserved for the frame, and zero the frame pointer. */ if (stack != NULL) { + npcb->pcb_nsaved = 0; tf2->tf_out[6] = (u_int64_t)(u_long)stack - (BIAS + CC64FSZ); tf2->tf_in[6] = 0; }