summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-06-10 02:27:40 +0000
committerRich Felker <dalias@aerifal.cx>2015-06-10 02:27:40 +0000
commitc30cbcb0a646b1f13a22c645616dce624465b883 (patch)
treef4bf3126b42b95645888d569ad97d24e20990280
parent276904c2f6bde3a31a24ebfa201482601d18b4f9 (diff)
downloadmusl-c30cbcb0a646b1f13a22c645616dce624465b883.tar.gz
implement arch-generic version of __unmapself
this can be used to put off writing an asm version of __unmapself for new archs, or as a permanent solution on archs where it's not practical or even possible to run momentarily with no stack. the concept here is simple: the caller takes a lock on a global shared stack and uses it to make the munmap and exit syscalls. the only trick is unlocking, which must be done after the thread exits, and this is achieved by using the set_tid_address syscall to have the kernel zero and futex-wake the lock word as part of the exit syscall.
-rw-r--r--src/thread/__unmapself.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/thread/__unmapself.c b/src/thread/__unmapself.c
index e69de29b..1d3bee1d 100644
--- a/src/thread/__unmapself.c
+++ b/src/thread/__unmapself.c
@@ -0,0 +1,29 @@
+#include "pthread_impl.h"
+#include "atomic.h"
+#include "syscall.h"
+/* cheat and reuse CRTJMP macro from dynlink code */
+#include "dynlink.h"
+
+static volatile int lock;
+static void *unmap_base;
+static size_t unmap_size;
+static char shared_stack[256];
+
+static void do_unmap()
+{
+ __syscall(SYS_munmap, unmap_base, unmap_size);
+ __syscall(SYS_exit);
+}
+
+void __unmapself(void *base, size_t size)
+{
+ int tid=__pthread_self()->tid;
+ char *stack = shared_stack + sizeof shared_stack;
+ stack -= (uintptr_t)stack % 16;
+ while (lock || a_cas(&lock, 0, tid))
+ a_spin();
+ __syscall(SYS_set_tid_address, &lock);
+ unmap_base = base;
+ unmap_size = size;
+ CRTJMP(do_unmap, stack);
+}