1/* 2 * Event loop thread implementation for unit tests 3 * 4 * Copyright Red Hat Inc., 2013, 2016 5 * 6 * Authors: 7 * Stefan Hajnoczi <stefanha@redhat.com> 8 * Paolo Bonzini <pbonzini@redhat.com> 9 * 10 * This work is licensed under the terms of the GNU GPL, version 2 or later. 11 * See the COPYING file in the top-level directory. 12 * 13 */ 14 15#include "qemu/osdep.h" 16#include "qapi/error.h" 17#include "block/aio.h" 18#include "qemu/main-loop.h" 19#include "qemu/rcu.h" 20#include "iothread.h" 21 22struct IOThread { 23 AioContext *ctx; 24 25 QemuThread thread; 26 QemuMutex init_done_lock; 27 QemuCond init_done_cond; /* is thread initialization done? */ 28 bool stopping; 29}; 30 31static __thread IOThread *my_iothread; 32 33AioContext *qemu_get_current_aio_context(void) 34{ 35 return my_iothread ? my_iothread->ctx : qemu_get_aio_context(); 36} 37 38static void *iothread_run(void *opaque) 39{ 40 IOThread *iothread = opaque; 41 42 rcu_register_thread(); 43 44 my_iothread = iothread; 45 qemu_mutex_lock(&iothread->init_done_lock); 46 iothread->ctx = aio_context_new(&error_abort); 47 qemu_cond_signal(&iothread->init_done_cond); 48 qemu_mutex_unlock(&iothread->init_done_lock); 49 50 while (!atomic_read(&iothread->stopping)) { 51 aio_poll(iothread->ctx, true); 52 } 53 54 rcu_unregister_thread(); 55 return NULL; 56} 57 58static void iothread_stop_bh(void *opaque) 59{ 60 IOThread *iothread = opaque; 61 62 iothread->stopping = true; 63} 64 65void iothread_join(IOThread *iothread) 66{ 67 aio_bh_schedule_oneshot(iothread->ctx, iothread_stop_bh, iothread); 68 qemu_thread_join(&iothread->thread); 69 qemu_cond_destroy(&iothread->init_done_cond); 70 qemu_mutex_destroy(&iothread->init_done_lock); 71 aio_context_unref(iothread->ctx); 72 g_free(iothread); 73} 74 75IOThread *iothread_new(void) 76{ 77 IOThread *iothread = g_new0(IOThread, 1); 78 79 qemu_mutex_init(&iothread->init_done_lock); 80 qemu_cond_init(&iothread->init_done_cond); 81 qemu_thread_create(&iothread->thread, NULL, iothread_run, 82 iothread, QEMU_THREAD_JOINABLE); 83 84 /* Wait for initialization to complete */ 85 qemu_mutex_lock(&iothread->init_done_lock); 86 while (iothread->ctx == NULL) { 87 qemu_cond_wait(&iothread->init_done_cond, 88 &iothread->init_done_lock); 89 } 90 qemu_mutex_unlock(&iothread->init_done_lock); 91 return iothread; 92} 93 94AioContext *iothread_get_aio_context(IOThread *iothread) 95{ 96 return iothread->ctx; 97} 98