summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2018-07-30 15:59:01 +0300
committerJari Vetoniemi <mailroxas@gmail.com>2018-07-30 15:59:01 +0300
commitf54936e762d660a155d05c7b52c2b424936ebf32 (patch)
tree563f0e3f4545abcf0e2ca60bec14cae6b291f1d6 /src
parent055295943756cf3cc8238dba741777b1e45fe948 (diff)
pthread: Implement pthread cleanup
Diffstat (limited to 'src')
-rw-r--r--src/libpthread.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/libpthread.c b/src/libpthread.c
index f001c47..5268f26 100644
--- a/src/libpthread.c
+++ b/src/libpthread.c
@@ -90,6 +90,15 @@ _Static_assert(sizeof(bionic_once_t) == sizeof(pthread_once_t), "bionic_once_t a
typedef long bionic_pthread_t;
_Static_assert(sizeof(bionic_pthread_t) == sizeof(pthread_t), "bionic_pthread_t and pthread_t size mismatch");
+struct bionic_pthread_cleanup_t {
+ union {
+ struct bionic_pthread_cleanup_t *prev;
+ __pthread_unwind_buf_t *glibc;
+ };
+ void (*routine)(void*);
+ void *arg;
+};
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
// For checking, if our glibc version is mapped to memory.
@@ -109,15 +118,32 @@ is_mapped(void *mem, const size_t sz)
}
void
-bionic___pthread_cleanup_push(void *c, void *routine, void *arg)
+bionic___pthread_cleanup_push(struct bionic_pthread_cleanup_t *c, void (*routine)(void*), void *arg)
{
- assert(0 && "implement");
+ assert(c && routine);
+ c->glibc = mmap(NULL, sizeof(*c->glibc), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+ c->routine = routine;
+ c->arg = arg;
+
+ int not_first_call;
+ if ((not_first_call = __sigsetjmp((struct __jmp_buf_tag*)(void*)c->glibc->__cancel_jmp_buf, 0))) {
+ routine(arg);
+ __pthread_unwind_next(c->glibc);
+ }
+
+ __pthread_register_cancel(c->glibc);
}
void
-bionic___pthread_cleanup_pop(void *c, int execute)
+bionic___pthread_cleanup_pop(struct bionic_pthread_cleanup_t *c, int execute)
{
- assert(0 && "implement");
+ assert(c && IS_MAPPED(c));
+ __pthread_unregister_cancel(c->glibc);
+
+ if (execute)
+ c->routine(c->arg);
+
+ munmap(c->glibc, sizeof(*c->glibc));
}
int