From ef57137f1b30545a477ab798d34a669b0abf5320 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Dec 2014 12:05:45 +0100 Subject: qemu-thread: add per-thread atexit functions Destructors are the main additional feature of pthread TLS compared to __thread. If we were using C++ (hint, hint!) we could have used thread-local objects with a destructor. Since we are not, instead, we add a simple Notifier-based API. Note that the notifier must be per-thread as well. We can add a global list as well later, perhaps. The Win32 implementation has some complications because a) detached threads used not to have a QemuThreadData; b) the main thread does not go through win32_start_routine, so we have to use atexit too. Signed-off-by: Paolo Bonzini Reviewed-by: Fam Zheng Message-id: 1417518350-6167-3-git-send-email-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi --- util/qemu-thread-posix.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'util/qemu-thread-posix.c') diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index d05a6497e1..41cb23df0c 100644 --- a/util/qemu-thread-posix.c +++ b/util/qemu-thread-posix.c @@ -26,6 +26,7 @@ #endif #include "qemu/thread.h" #include "qemu/atomic.h" +#include "qemu/notify.h" static bool name_threads; @@ -401,6 +402,42 @@ void qemu_event_wait(QemuEvent *ev) } } +static pthread_key_t exit_key; + +union NotifierThreadData { + void *ptr; + NotifierList list; +}; +QEMU_BUILD_BUG_ON(sizeof(union NotifierThreadData) != sizeof(void *)); + +void qemu_thread_atexit_add(Notifier *notifier) +{ + union NotifierThreadData ntd; + ntd.ptr = pthread_getspecific(exit_key); + notifier_list_add(&ntd.list, notifier); + pthread_setspecific(exit_key, ntd.ptr); +} + +void qemu_thread_atexit_remove(Notifier *notifier) +{ + union NotifierThreadData ntd; + ntd.ptr = pthread_getspecific(exit_key); + notifier_remove(notifier); + pthread_setspecific(exit_key, ntd.ptr); +} + +static void qemu_thread_atexit_run(void *arg) +{ + union NotifierThreadData ntd = { .ptr = arg }; + notifier_list_notify(&ntd.list, NULL); +} + +static void __attribute__((constructor)) qemu_thread_atexit_init(void) +{ + pthread_key_create(&exit_key, qemu_thread_atexit_run); +} + + /* Attempt to set the threads name; note that this is for debug, so * we're not going to fail if we can't set it. */ -- cgit 1.4.1