rather than allocating memory for _Thread struct and stack together, this diff[1] changes the allocation by pulling apart the stack of the thread_t struct, so now only the stack segment has the MAP_STACK flag for passing stack-register checking.
tested on amd64(MAP_STACK bits in). acme(1)/sam(1) works fine! [1] http://shutpandhack.org/~gsoares/plan9port_map_stack.diff
Index: Makefile =================================================================== RCS file: /cvs/ports/plan9/plan9port/Makefile,v retrieving revision 1.24 diff -u -p -r1.24 Makefile --- Makefile 20 Jan 2018 03:29:56 -0000 1.24 +++ Makefile 21 Mar 2018 02:02:26 -0000 @@ -4,6 +4,7 @@ ONLY_FOR_ARCHS = amd64 i386 powerpc BROKEN-powerpc = threading issues COMMENT = Plan 9 from user space +REVISION = 0 DISTNAME = plan9port-20180117 Index: patches/patch-src_libthread_thread_c =================================================================== RCS file: patches/patch-src_libthread_thread_c diff -N patches/patch-src_libthread_thread_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_libthread_thread_c 21 Mar 2018 02:02:26 -0000 @@ -0,0 +1,46 @@ +$OpenBSD$ + +Index: src/libthread/thread.c +--- src/libthread/thread.c.orig ++++ src/libthread/thread.c +@@ -107,12 +107,18 @@ threadalloc(void (*fn)(void*), void *arg, uint stack) + uint x, y; + ulong z; + +- /* allocate the task and stack together */ +- t = malloc(sizeof *t+stack); ++ /* allocate the task */ ++ t = malloc(sizeof *t); + if(t == nil) + sysfatal("threadalloc malloc: %r"); + memset(t, 0, sizeof *t); +- t->stk = (uchar*)(t+1); ++ /* allocate the real stack */ ++ t->stk = mmap(NULL, stack, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0); ++ if (t->stk == MAP_FAILED) { ++ free(t); ++ sysfatal("threadalloc malloc: %r"); ++ } + t->stksize = stack; + t->id = incref(&threadidref); + //print("fn=%p arg=%p\n", fn, arg); +@@ -133,8 +139,8 @@ threadalloc(void (*fn)(void*), void *arg, uint stack) + + /* call makecontext to do the real work. */ + /* leave a few words open on both ends */ +- t->context.uc.uc_stack.ss_sp = (void*)(t->stk+8); +- t->context.uc.uc_stack.ss_size = t->stksize-64; ++ t->context.uc.uc_stack.ss_sp = t->stk; ++ t->context.uc.uc_stack.ss_size = t->stksize; + #if defined(__sun__) && !defined(__MAKECONTEXT_V2_SOURCE) /* sigh */ + /* can avoid this with __MAKECONTEXT_V2_SOURCE but only on SunOS 5.9 */ + t->context.uc.uc_stack.ss_sp = +@@ -364,6 +370,7 @@ procscheduler(Proc *p) + delthreadinproc(p, t); + p->nthread--; + /*print("nthread %d\n", p->nthread); */ ++ munmap(t->stk, t->stksize); + free(t); + } + } Index: patches/patch-src_libthread_threadimpl_h =================================================================== RCS file: patches/patch-src_libthread_threadimpl_h diff -N patches/patch-src_libthread_threadimpl_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_libthread_threadimpl_h 21 Mar 2018 02:02:26 -0000 @@ -0,0 +1,14 @@ +$OpenBSD$ + +Index: src/libthread/threadimpl.h +--- src/libthread/threadimpl.h.orig ++++ src/libthread/threadimpl.h +@@ -10,6 +10,8 @@ + # define _XOPEN_SOURCE /* for Snow Leopard */ + # endif + # include <ucontext.h> ++#elif defined(__OpenBSD__) ++# include <sys/mman.h> + #endif + #include <sys/utsname.h> + #include "libc.h"