From: Paolo Bonzini <pbonz...@redhat.com> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> Reviewed-by: Mike Day <ncm...@ncultra.org> --- docs/rcu.txt | 13 +++++++------ util/qemu-thread-posix.c | 28 +++++++++++++++++++++++++++- util/qemu-thread-win32.c | 2 ++ 3 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/docs/rcu.txt b/docs/rcu.txt index 19e4840..5736676 100644 --- a/docs/rcu.txt +++ b/docs/rcu.txt @@ -122,8 +122,8 @@ on many POSIX systems other than Linux and Solaris). For this reason, QEMU's RCU implementation resorts to manual annotation of "quiescent states", i.e. points where no RCU read-side critical -section can be active. All threads that participate in the RCU mechanism -need to annotate such points. +section can be active. All threads created with qemu_thread_create +participate in the RCU mechanism and need to annotate such points. Marking quiescent states is done with the following three APIs: @@ -144,8 +144,8 @@ Marking quiescent states is done with the following three APIs: thread. -Furthermore, threads that participate in the RCU mechanism must communicate -this fact using the following APIs: +The following APIs can be used to use RCU in a thread that is not +created with qemu_thread_create(): void rcu_register_thread(void); @@ -160,8 +160,9 @@ this fact using the following APIs: either manually or by using the QemuCond/QemuSemaphore/QemuEvent APIs. -Note that these APIs are relatively heavyweight, and should _not_ be -nested. +Note that these APIs are relatively heavyweight, should _not_ be +nested, and should not be called in threads that are created with +qemu_thread_create(). DIFFERENCES WITH LINUX diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c index 37dd298..2371176 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/rcu.h" static void error_exit(int err, const char *msg) { @@ -388,6 +389,26 @@ void qemu_event_wait(QemuEvent *ev) } +typedef struct QemuThreadData { + /* Passed to win32_start_routine. */ + void *(*start_routine)(void *); + void *arg; +} QemuThreadData; + +static void *thread_start_routine(void *arg) +{ + QemuThreadData *data = (QemuThreadData *) arg; + void *(*start_routine)(void *) = data->start_routine; + void *thread_arg = data->arg; + void *ret; + + rcu_register_thread(); + g_free(data); + ret = start_routine(thread_arg); + rcu_unregister_thread(); + return ret; +} + void qemu_thread_create(QemuThread *thread, void *(*start_routine)(void*), void *arg, int mode) @@ -395,6 +416,11 @@ void qemu_thread_create(QemuThread *thread, sigset_t set, oldset; int err; pthread_attr_t attr; + QemuThreadData *data; + + data = g_malloc(sizeof(*data)); + data->start_routine = start_routine; + data->arg = arg; err = pthread_attr_init(&attr); if (err) { @@ -410,7 +436,7 @@ void qemu_thread_create(QemuThread *thread, /* Leave signal handling to the iothread. */ sigfillset(&set); pthread_sigmask(SIG_SETMASK, &set, &oldset); - err = pthread_create(&thread->thread, &attr, start_routine, arg); + err = pthread_create(&thread->thread, &attr, thread_start_routine, data); if (err) error_exit(err, __func__); diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c index 27a5217..0c4850d 100644 --- a/util/qemu-thread-win32.c +++ b/util/qemu-thread-win32.c @@ -278,6 +278,7 @@ static unsigned __stdcall win32_start_routine(void *arg) data = NULL; } qemu_thread_data = data; + rcu_register_thread(); qemu_thread_exit(start_routine(thread_arg)); abort(); } @@ -293,6 +294,7 @@ void qemu_thread_exit(void *arg) data->exited = true; LeaveCriticalSection(&data->cs); } + rcu_unregister_thread(); _endthreadex(0); } -- 1.8.3.1