tlibthread: use mmap to allocate OpenBSD stacks - plan9port - [fork] Plan 9 from user space (HTM) git clone git://src.adamsgaard.dk/plan9port (DIR) Log (DIR) Files (DIR) Refs (DIR) README (DIR) LICENSE --- (DIR) commit 8c573cab6819c69142389d36b978b3c683771afe (DIR) parent 4ae529dbfe8573ae105d0d66f7f453c4f850fa1f (HTM) Author: Russ Cox <rsc@swtch.com> Date: Tue, 14 Jan 2020 12:40:09 -0500 libthread: use mmap to allocate OpenBSD stacks Should fix faults on OpenBSD. Fixes #218. Fixes #226. Diffstat: M src/libthread/Darwin-x86_64-swapco… | 8 ++++++++ A src/libthread/stkmalloc.c | 13 +++++++++++++ A src/libthread/stkmmap.c | 25 +++++++++++++++++++++++++ M src/libthread/sysofiles.sh | 12 ++++++------ M src/libthread/thread.c | 9 +++++++-- M src/libthread/threadimpl.h | 2 ++ 6 files changed, 61 insertions(+), 8 deletions(-) --- (DIR) diff --git a/src/libthread/Darwin-x86_64-swapcontext.c b/src/libthread/Darwin-x86_64-swapcontext.c t@@ -16,6 +16,14 @@ makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) va_end(arg); sp = (uintptr*)((char*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size); + /* + * Stack pointer at call instruction (before return address + * gets pushed) must be 16-byte aligned. + */ + if((uintptr)sp%4) + abort(); + while((uintptr)sp%16 != 0) + sp--; *--sp = 0; // fn's return address *--sp = (uintptr)fn; // return address of setcontext uc->mc.sp = (uintptr)sp; (DIR) diff --git a/src/libthread/stkmalloc.c b/src/libthread/stkmalloc.c t@@ -0,0 +1,13 @@ +#include "threadimpl.h" + +void* +_threadstkalloc(int n) +{ + return malloc(n); +} + +void +_threadstkfree(void *v, int n) +{ + free(v); +} (DIR) diff --git a/src/libthread/stkmmap.c b/src/libthread/stkmmap.c t@@ -0,0 +1,25 @@ +#include <u.h> +#include <sys/mman.h> +#include "threadimpl.h" + +#ifndef MAP_STACK +#define MAP_STACK 0 +#endif + +void* +_threadstkalloc(int n) +{ + void *p; + + p = mmap(nil, n, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_STACK, -1, 0); + if(p == (void*)-1) + return nil; + return p; +} + +void +_threadstkfree(void *v, int n) +{ + if(n > 0) + munmap(v, n); +} (DIR) diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh t@@ -6,22 +6,22 @@ tag="$OBJTYPE-$SYSNAME-${SYSVERSION:-`uname -r`}-${CC9:-cc}" case "$tag" in *-Linux-2.[0-5]*) # will have to fix this for linux power pc - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; *-FreeBSD-[0-4].*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; *-NetBSD-*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; *-Darwin-10.[5-6].* | *-Darwin-[89].*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME-${OBJTYPE}.o pthread.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME-${OBJTYPE}.o pthread.o stkmalloc.o ;; *-OpenBSD-*) - echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o + echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o stkmmap.o ;; *) - echo pthread.o + echo pthread.o stkmalloc.o esac case "$OBJTYPE-$SYSNAME" in (DIR) diff --git a/src/libthread/thread.c b/src/libthread/thread.c t@@ -109,7 +109,7 @@ threadalloc(void (*fn)(void*), void *arg, uint stack) ulong z; /* allocate the task and stack together */ - t = malloc(sizeof *t+stack); + t = malloc(sizeof *t); if(t == nil) sysfatal("threadalloc malloc: %r"); memset(t, 0, sizeof *t); t@@ -122,7 +122,9 @@ threadalloc(void (*fn)(void*), void *arg, uint stack) /* do a reasonable initialization */ if(stack == 0) return t; - t->stk = (uchar*)(t+1); + t->stk = _threadstkalloc(stack); + if(t->stk == nil) + sysfatal("threadalloc malloc stack: %r"); t->stksize = stack; memset(&t->context.uc, 0, sizeof t->context.uc); sigemptyset(&zero); t@@ -353,6 +355,7 @@ Top: delthreadinproc(p, t); p->nthread--; /*print("nthread %d\n", p->nthread); */ + _threadstkfree(t->stk, t->stksize); free(t); } t@@ -509,6 +512,8 @@ needstack(int n) _Thread *t; t = proc()->thread; + if(t->stk == nil) + return; if((char*)&t <= (char*)t->stk || (char*)&t - (char*)t->stk < 256+n){ (DIR) diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h t@@ -209,3 +209,5 @@ extern void _threadsetupdaemonize(void); extern void _threaddodaemonize(char*); extern void _threadpexit(void); extern void _threaddaemonize(void); +extern void *_threadstkalloc(int); +extern void _threadstkfree(void*, int);