commit 8c573cab6819c69142389d36b978b3c683771afe from: Russ Cox date: Tue Jan 14 18:58:47 2020 UTC libthread: use mmap to allocate OpenBSD stacks Should fix faults on OpenBSD. Fixes #218. Fixes #226. commit - 4ae529dbfe8573ae105d0d66f7f453c4f850fa1f commit + 8c573cab6819c69142389d36b978b3c683771afe blob - 27931456d6d0d9bf6377056fe280ef31437c4a62 blob + c29ddb5ee16e74c4f549477efa7d656ee2940f15 --- src/libthread/Darwin-x86_64-swapcontext.c +++ 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; blob - 9eeea606bb53c1ddae3cef5c1ecf7ba0059c7c16 blob + f76b975ad00ef75ea9b72bb586bad3716cbebfc3 --- src/libthread/sysofiles.sh +++ src/libthread/sysofiles.sh @@ -6,22 +6,22 @@ tag="$OBJTYPE-$SYSNAME-${SYSVERSION:-`uname -r`}-${CC9 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 blob - /dev/null blob + 083aea1b916d022723fd0eba27ccd1dc49b292f8 (mode 644) --- /dev/null +++ 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); +} blob - /dev/null blob + f4a24630843b2477a18908aa9b9e00391fa5ccc3 (mode 644) --- /dev/null +++ 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); +} blob - d041efcccfb416827c4c6c7a70d86d763caf26a9 blob + 2e654863f2055e66df0e3b2f254395036cf340d2 --- src/libthread/thread.c +++ 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){ blob - 76ca57e5c7474e871a5867f5b3fa70b9dee0bdf9 blob + 6671f23cf9c7de71d6c83577fd3cc55cb0d20a87 --- src/libthread/threadimpl.h +++ 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);