From 8c573cab6819c69142389d36b978b3c683771afe Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 12:40:09 -0500 Subject: libthread: use mmap to allocate OpenBSD stacks Should fix faults on OpenBSD. Fixes #218. Fixes #226. --- src/libthread/Darwin-x86_64-swapcontext.c | 8 ++++++++ src/libthread/stkmalloc.c | 13 +++++++++++++ src/libthread/stkmmap.c | 25 +++++++++++++++++++++++++ src/libthread/sysofiles.sh | 12 ++++++------ src/libthread/thread.c | 9 +++++++-- src/libthread/threadimpl.h | 2 ++ 6 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 src/libthread/stkmalloc.c create mode 100644 src/libthread/stkmmap.c (limited to 'src/libthread') diff --git a/src/libthread/Darwin-x86_64-swapcontext.c b/src/libthread/Darwin-x86_64-swapcontext.c index 27931456..c29ddb5e 100644 --- a/src/libthread/Darwin-x86_64-swapcontext.c +++ b/src/libthread/Darwin-x86_64-swapcontext.c @@ -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; diff --git a/src/libthread/stkmalloc.c b/src/libthread/stkmalloc.c new file mode 100644 index 00000000..083aea1b --- /dev/null +++ b/src/libthread/stkmalloc.c @@ -0,0 +1,13 @@ +#include "threadimpl.h" + +void* +_threadstkalloc(int n) +{ + return malloc(n); +} + +void +_threadstkfree(void *v, int n) +{ + free(v); +} diff --git a/src/libthread/stkmmap.c b/src/libthread/stkmmap.c new file mode 100644 index 00000000..f4a24630 --- /dev/null +++ b/src/libthread/stkmmap.c @@ -0,0 +1,25 @@ +#include +#include +#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); +} diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index 9eeea606..f76b975a 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -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 diff --git a/src/libthread/thread.c b/src/libthread/thread.c index d041efcc..2e654863 100644 --- a/src/libthread/thread.c +++ b/src/libthread/thread.c @@ -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); @@ -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); @@ -353,6 +355,7 @@ Top: delthreadinproc(p, t); p->nthread--; /*print("nthread %d\n", p->nthread); */ + _threadstkfree(t->stk, t->stksize); free(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){ diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index 76ca57e5..6671f23c 100644 --- a/src/libthread/threadimpl.h +++ b/src/libthread/threadimpl.h @@ -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); -- cgit v1.2.3