From 67eb8c6c04a1b6c6fb85cf9cd6d7bdde489c4d5d Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 11 Sep 2018 22:16:41 -0500 Subject: cxx_thread: Add __cxa_thread_atexit_impl Signed-off-by: Samuel Holland --- CHANGELOG.rst | 5 +++++ Makefile | 1 + libgcompat/cxx_thread.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 libgcompat/cxx_thread.c diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ee9851d..2902cb3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,11 @@ Build system * Allow building against libucontext. +cxx_thread +---------- + +* Add __cxa_thread_atexit_impl. + math ---- diff --git a/Makefile b/Makefile index 06af84f..74c25f6 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ LIBGCOMPAT_INCLUDE = \ libgcompat/alias.h LIBGCOMPAT_SRC = \ + libgcompat/cxx_thread.c \ libgcompat/dlfcn.c \ libgcompat/error.c \ libgcompat/execinfo.c \ diff --git a/libgcompat/cxx_thread.c b/libgcompat/cxx_thread.c new file mode 100644 index 0000000..105e4c5 --- /dev/null +++ b/libgcompat/cxx_thread.c @@ -0,0 +1,56 @@ +#include /* NULL, pthread_{key,once,{get,set}specific} */ +#include /* malloc, free */ + +#include "internal.h" + +struct dtor_node { + struct dtor_node *next; + void (*func)(void *); + void *obj; +}; + +static pthread_key_t key; +static pthread_once_t once = PTHREAD_ONCE_INIT; + +static void run_dtors(void *head) +{ + struct dtor_node *next, *node = head; + + while (node != NULL) { + next = node->next; + node->func(node->obj); + free(node); + node = next; + } +} + +static void create_key(void) +{ + int res = pthread_key_create(&key, run_dtors); + + GCOMPAT__assert_with_reason(res, "No key for thread_atexit list"); +} + +/** + * Register a destructor to run at thread exit. + * + * See + * https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables + */ +int __cxa_thread_atexit_impl(void (*func)(void *), void *obj, void *dso_symbol) +{ + struct dtor_node *node; + + pthread_once(&once, create_key); + + node = malloc(sizeof(*node)); + GCOMPAT__assert_with_reason(node, "No memory for thread_atexit node"); + node->next = pthread_getspecific(key); + node->func = func; + node->obj = obj; + + int res = pthread_setspecific(key, node); + GCOMPAT__assert_with_reason(!res, "Cannot update thread_atexit list"); + + return 0; +} -- cgit v1.2.3-70-g09d2