summary refs log tree commit diff stats
path: root/util/qemu-thread-posix.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-12-02 12:05:45 +0100
committerStefan Hajnoczi <stefanha@redhat.com>2015-01-13 13:43:29 +0000
commitef57137f1b30545a477ab798d34a669b0abf5320 (patch)
tree72fbda74c56d638e7ee78c0e21d8053219d385f0 /util/qemu-thread-posix.c
parentd1d1b206b07977fe0e75b0254e5b50c215c97803 (diff)
downloadfocaccia-qemu-ef57137f1b30545a477ab798d34a669b0abf5320.tar.gz
focaccia-qemu-ef57137f1b30545a477ab798d34a669b0abf5320.zip
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 <pbonzini@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Message-id: 1417518350-6167-3-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'util/qemu-thread-posix.c')
-rw-r--r--util/qemu-thread-posix.c37
1 files changed, 37 insertions, 0 deletions
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.
  */