URI: 
       tlibthread: use consistent stack calculation code in makecontext - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 41b3e8b9893a8561af7e85ca98444bc284b4013d
   DIR parent ac8042dfa9819f76ccfedd4aa36c1239322808b8
  HTML Author: Russ Cox <rsc@swtch.com>
       Date:   Sun, 19 Jan 2020 22:39:22 -0500
       
       libthread: use consistent stack calculation code in makecontext
       
       Also reduce duplication: makecontext is per-arch not per-os-arch.
       
       May fix #353.
       
       Diffstat:
         A src/libthread/386-ucontext.c        |      22 ++++++++++++++++++++++
         M src/libthread/COPYRIGHT             |       6 +++---
         D src/libthread/Darwin-x86_64-swapco… |      38 -------------------------------
         D src/libthread/Linux-arm-swapcontex… |      24 ------------------------
         M src/libthread/NetBSD.c              |      25 -------------------------
         D src/libthread/OpenBSD-386.c         |      22 ----------------------
         D src/libthread/OpenBSD-power.c       |      24 ------------------------
         D src/libthread/OpenBSD-x86_64.c      |      30 ------------------------------
         A src/libthread/arm-ucontext.c        |      24 ++++++++++++++++++++++++
         M src/libthread/mkfile                |       4 ++--
         A src/libthread/power-ucontext.c      |      26 ++++++++++++++++++++++++++
         R src/libthread/Linux-sparc64-swapco… |       0 
         M src/libthread/sysofiles.sh          |      29 +++++++++++++++++++++--------
         M src/libthread/threadimpl.h          |       3 +++
         A src/libthread/x86_64-ucontext.c     |      28 ++++++++++++++++++++++++++++
       
       15 files changed, 129 insertions(+), 176 deletions(-)
       ---
   DIR diff --git a/src/libthread/386-ucontext.c b/src/libthread/386-ucontext.c
       t@@ -0,0 +1,22 @@
       +#include "threadimpl.h"
       +
       +void
       +makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
       +{
       +        int *sp;
       +
       +        sp = USPALIGN(ucp, 4);
       +        sp -= argc;
       +        memmove(sp, &argc+1, argc*sizeof(int));
       +        *--sp = 0;                /* return address */
       +        ucp->uc_mcontext.mc_eip = (long)func;
       +        ucp->uc_mcontext.mc_esp = (int)sp;
       +}
       +
       +int
       +swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       +{
       +        if(getcontext(oucp) == 0)
       +                setcontext(ucp);
       +        return 0;
       +}
   DIR diff --git a/src/libthread/COPYRIGHT b/src/libthread/COPYRIGHT
       t@@ -45,9 +45,9 @@ Contains parts of an earlier library that has:
        
        ===
        
       -The above notices do *NOT* apply to Linux-sparc64-context.S 
       -or to Linux-sparc64-swapcontext.c.  Those are functions from 
       +The above notices do *NOT* apply to Linux-sparc64-context.S
       +or to sparc64-ucontext.c.  Those are functions from
        the GNU C library and are provided for systems that use the GNU C
       -library but somehow are missing those functions.  They are 
       +library but somehow are missing those functions.  They are
        distributed under the Lesser GPL; see COPYING.SPARC64-CONTEXT.
        
   DIR diff --git a/src/libthread/Darwin-x86_64-swapcontext.c b/src/libthread/Darwin-x86_64-swapcontext.c
       t@@ -1,38 +0,0 @@
       -#include "threadimpl.h"
       -
       -void
       -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
       -{
       -        uintptr *sp;
       -        va_list arg;
       -
       -//fprint(2, "makecontext %d\n", argc);
       -        if(argc != 2)
       -                sysfatal("libthread: makecontext misused");
       -        va_start(arg, argc);
       -        uc->mc.di = va_arg(arg, uint);
       -        uc->mc.si = va_arg(arg, uint);
       -//fprint(2, "%ux %ux\n", uc->mc.di, uc->mc.si);
       -        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;
       -}
       -
       -int
       -swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       -{
       -        if(getcontext(oucp) == 0)
       -                setcontext(ucp);
       -        return 0;
       -}
   DIR diff --git a/src/libthread/Linux-arm-swapcontext.c b/src/libthread/Linux-arm-swapcontext.c
       t@@ -1,24 +0,0 @@
       -#include "threadimpl.h"
       -
       -void
       -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
       -{
       -        int i, *sp;
       -        va_list arg;
       -
       -        sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4;
       -        va_start(arg, argc);
       -        for(i=0; i<4 && i<argc; i++)
       -                (&uc->uc_mcontext.arm_r0)[i] = va_arg(arg, uint);
       -        va_end(arg);
       -        uc->uc_mcontext.arm_sp = (uint)sp;
       -        uc->uc_mcontext.arm_lr = (uint)fn;
       -}
       -
       -int
       -swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
       -{
       -        if(getcontext(oucp) == 0)
       -                setcontext(ucp);
       -        return 0;
       -}
   DIR diff --git a/src/libthread/NetBSD.c b/src/libthread/NetBSD.c
       t@@ -435,28 +435,3 @@ _threadpexit(void)
        {
                _exit(0);
        }
       -
       -#ifdef __arm__
       -void
       -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
       -{
       -        int i, *sp;
       -        va_list arg;
       -
       -        sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4;
       -        va_start(arg, argc);
       -        for(i=0; i<4 && i<argc; i++)
       -                uc->uc_mcontext.gregs[i] = va_arg(arg, uint);
       -        va_end(arg);
       -        uc->uc_mcontext.gregs[13] = (uint)sp;
       -        uc->uc_mcontext.gregs[14] = (uint)fn;
       -}
       -
       -int
       -swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
       -{
       -        if(getcontext(oucp) == 0)
       -                setcontext(ucp);
       -        return 0;
       -}
       -#endif
   DIR diff --git a/src/libthread/OpenBSD-386.c b/src/libthread/OpenBSD-386.c
       t@@ -1,22 +0,0 @@
       -#include "threadimpl.h"
       -
       -void
       -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
       -{
       -        int *sp;
       -
       -        sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4;
       -        sp -= argc;
       -        memmove(sp, &argc+1, argc*sizeof(int));
       -        *--sp = 0;                /* return address */
       -        ucp->uc_mcontext.mc_eip = (long)func;
       -        ucp->uc_mcontext.mc_esp = (int)sp;
       -}
       -
       -int
       -swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       -{
       -        if(getcontext(oucp) == 0)
       -                setcontext(ucp);
       -        return 0;
       -}
   DIR diff --git a/src/libthread/OpenBSD-power.c b/src/libthread/OpenBSD-power.c
       t@@ -1,24 +0,0 @@
       -#include "threadimpl.h"
       -
       -void
       -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
       -{
       -        ulong *sp, *tos;
       -        va_list arg;
       -
       -        tos = (ulong*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(ulong);
       -        sp = (ulong*)((ulong)(tos-16) & ~15);
       -        ucp->mc.pc = (long)func;
       -        ucp->mc.sp = (long)sp;
       -        va_start(arg, argc);
       -        ucp->mc.r3 = va_arg(arg, long);
       -        va_end(arg);
       -}
       -
       -int
       -swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       -{
       -        if(getcontext(oucp) == 0)
       -                setcontext(ucp);
       -        return 0;
       -}
   DIR diff --git a/src/libthread/OpenBSD-x86_64.c b/src/libthread/OpenBSD-x86_64.c
       t@@ -1,30 +0,0 @@
       -#include "threadimpl.h"
       -
       -void
       -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
       -{
       -        uintptr *sp;
       -        va_list arg;
       -
       -//fprint(2, "makecontext %d\n", argc);
       -        if(argc != 2)
       -                sysfatal("libthread: makecontext misused");
       -        va_start(arg, argc);
       -        uc->mc.di = va_arg(arg, uint);
       -        uc->mc.si = va_arg(arg, uint);
       -//fprint(2, "%ux %ux\n", uc->mc.di, uc->mc.si);
       -        va_end(arg);
       -
       -        sp = (uintptr*)((char*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size);
       -        *--sp = 0;  // fn's return address
       -        *--sp = (uintptr)fn;  // return address of setcontext
       -        uc->mc.sp = (uintptr)sp;
       -}
       -
       -int
       -swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       -{
       -        if(getcontext(oucp) == 0)
       -                setcontext(ucp);
       -        return 0;
       -}
   DIR diff --git a/src/libthread/arm-ucontext.c b/src/libthread/arm-ucontext.c
       t@@ -0,0 +1,24 @@
       +#include "threadimpl.h"
       +
       +void
       +makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
       +{
       +        int i, *sp;
       +        va_list arg;
       +
       +        sp = USPALIGN(uc, 4);
       +        va_start(arg, argc);
       +        for(i=0; i<4 && i<argc; i++)
       +                (&uc->uc_mcontext.arm_r0)[i] = va_arg(arg, uint);
       +        va_end(arg);
       +        uc->uc_mcontext.arm_sp = (uint)sp;
       +        uc->uc_mcontext.arm_lr = (uint)fn;
       +}
       +
       +int
       +swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
       +{
       +        if(getcontext(oucp) == 0)
       +                setcontext(ucp);
       +        return 0;
       +}
   DIR diff --git a/src/libthread/mkfile b/src/libthread/mkfile
       t@@ -37,8 +37,8 @@ OpenBSD-%-asm.$O:        OpenBSD-%-asm.S
        Linux-sparc64-context.$O: Linux-sparc64-context.S
                $CC -m64 -mcpu=v9 $CFLAGS Linux-sparc64-context.S
        
       -Linux-sparc64-swapcontext.$O: Linux-sparc64-swapcontext.c
       -        $CC -m64 -mcpu=v9 $CFLAGS Linux-sparc64-swapcontext.c
       +sparc64-ucontext.$O: sparc64-ucontext.c
       +        $CC -m64 -mcpu=v9 $CFLAGS sparc64-ucontext.c
        
        test:V: tprimes tspawn
                primes 1 10007 >p1.txt
   DIR diff --git a/src/libthread/power-ucontext.c b/src/libthread/power-ucontext.c
       t@@ -0,0 +1,26 @@
       +#include "threadimpl.h"
       +
       +void
       +makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
       +{
       +        ulong *sp, *tos;
       +        va_list arg;
       +
       +        if(argc != 2)
       +                sysfatal("libthread: makecontext misused");
       +        sp = USPALIGN(ucp, 16);
       +        ucp->mc.pc = (long)func;
       +        ucp->mc.sp = (long)sp;
       +        va_start(arg, argc);
       +        ucp->mc.r3 = va_arg(arg, long);
       +        ucp->mc.r4 = va_arg(arg, long);
       +        va_end(arg);
       +}
       +
       +int
       +swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       +{
       +        if(getcontext(oucp) == 0)
       +                setcontext(ucp);
       +        return 0;
       +}
   DIR diff --git a/src/libthread/Linux-sparc64-swapcontext.c b/src/libthread/sparc64-ucontext.c
   DIR diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh
       t@@ -7,24 +7,37 @@ NetBSD)
                echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o
                ;;
        OpenBSD)
       -        echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o stkmmap.o
       +        echo ${SYSNAME}-${OBJTYPE}-asm.o pthread.o stkmmap.o
                ;;
        *)
                echo pthread.o stkmalloc.o
        esac
        
       +# Various libc don't supply swapcontext, makecontext, so we do.
        case "$OBJTYPE-$SYSNAME" in
       -sparc64-Linux)
       -        # Debian glibc doesn't supply swapcontext, makecontext
       -        # so we supply our own copy from the latest glibc.
       -        echo Linux-sparc64-context.o Linux-sparc64-swapcontext.o
       +386-OpenBSD)
       +        echo 386-ucontext.o
                ;;
        arm-Linux)
       -        # ARM doesn't supply them either.
       -        echo Linux-arm-context.o Linux-arm-swapcontext.o
       +        echo arm-ucontext.o
       +        echo Linux-arm-context.o # setcontext, getcontext
       +        ;;
       +arm-NetBSD)
       +        echo arm-ucontext.o
       +        ;;
       +power-OpenBSD)
       +        echo power-ucontext.o
       +        ;;
       +sparc64-Linux)
       +        echo sparc64-ucontext.o
       +        echo Linux-sparc64-swapcontext.o # setcontext, getcontext
                ;;
        x86_64-Darwin)
       -        echo Darwin-x86_64-asm.o Darwin-x86_64-swapcontext.o
       +        echo x86_64-ucontext.o
       +        echo Darwin-x86_64-asm.o # setcontext, getcontext
       +        ;;
       +x86_64-OpenBSD)
       +        echo x86_64-ucontext.o
                ;;
        esac
        
   DIR diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
       t@@ -188,3 +188,6 @@ extern void _threadpexit(void);
        extern void _threaddaemonize(void);
        extern void *_threadstkalloc(int);
        extern void _threadstkfree(void*, int);
       +
       +#define USPALIGN(ucp, align) \
       +        (void*)((((uintptr)(ucp)->uc_stack.ss_sp+(ucp)->uc_stack.ss_size)-(align))&~((align)-1))
   DIR diff --git a/src/libthread/x86_64-ucontext.c b/src/libthread/x86_64-ucontext.c
       t@@ -0,0 +1,28 @@
       +#include "threadimpl.h"
       +
       +void
       +makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
       +{
       +        uintptr *sp;
       +        va_list arg;
       +
       +        if(argc != 2)
       +                sysfatal("libthread: makecontext misused");
       +        va_start(arg, argc);
       +        uc->mc.di = va_arg(arg, uint);
       +        uc->mc.si = va_arg(arg, uint);
       +        va_end(arg);
       +
       +        sp = USPALIGN(uc, 16);
       +        *--sp = 0;  // fn's return address
       +        *--sp = (uintptr)fn;  // return address of setcontext
       +        uc->mc.sp = (uintptr)sp;
       +}
       +
       +int
       +swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       +{
       +        if(getcontext(oucp) == 0)
       +                setcontext(ucp);
       +        return 0;
       +}