]>
Commit | Line | Data |
---|---|---|
0c330a73 PB |
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 | ||
22 | struct 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 | ||
31 | static __thread IOThread *my_iothread; | |
32 | ||
33 | AioContext *qemu_get_current_aio_context(void) | |
34 | { | |
35 | return my_iothread ? my_iothread->ctx : qemu_get_aio_context(); | |
36 | } | |
37 | ||
38 | static 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 | ||
58 | void 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 | ||
69 | IOThread *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 | ||
88 | AioContext *iothread_get_aio_context(IOThread *iothread) | |
89 | { | |
90 | return iothread->ctx; | |
91 | } |