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);