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 58void iothread_join(IOThread *iothread) 59{ 60 iothread->stopping = true; 61 aio_notify(iothread->ctx); 62 qemu_thread_join(&iothread->thread); 63 qemu_cond_destroy(&iothread->init_done_cond); 64 qemu_mutex_destroy(&iothread->init_done_lock); 65 aio_context_unref(iothread->ctx); 66 g_free(iothread); 67} 68 69IOThread *iothread_new(void) 70{ 71 IOThread *iothread = g_new0(IOThread, 1); 72 73 qemu_mutex_init(&iothread->init_done_lock); 74 qemu_cond_init(&iothread->init_done_cond); 75 qemu_thread_create(&iothread->thread, NULL, iothread_run, 76 iothread, QEMU_THREAD_JOINABLE); 77 78 /* Wait for initialization to complete */ 79 qemu_mutex_lock(&iothread->init_done_lock); 80 while (iothread->ctx == NULL) { 81 qemu_cond_wait(&iothread->init_done_cond, 82 &iothread->init_done_lock); 83 } 84 qemu_mutex_unlock(&iothread->init_done_lock); 85 return iothread; 86} 87 88AioContext *iothread_get_aio_context(IOThread *iothread) 89{ 90 return iothread->ctx; 91} 92