tlibthread: use consistent stack calculation code in makecontext - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit 41b3e8b9893a8561af7e85ca98444bc284b4013d
parent ac8042dfa9819f76ccfedd4aa36c1239322808b8
Author: Russ Cox 
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(-)
---
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;
+}
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.
 
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;
-}
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 && iuc_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;
-}
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 && iuc_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
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;
-}
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;
-}
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;
-}
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 && iuc_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;
+}
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
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;
+}
diff --git a/src/libthread/Linux-sparc64-swapcontext.c b/src/libthread/sparc64-ucontext.c
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
 
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))
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;
+}