| 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;
+} |