]>
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 <[email protected]> | |
8 | * Paolo Bonzini <[email protected]> | |
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 | ||
69de4844 | 58 | static void iothread_stop_bh(void *opaque) |
0c330a73 | 59 | { |
69de4844 SH |
60 | IOThread *iothread = opaque; |
61 | ||
0c330a73 | 62 | iothread->stopping = true; |
69de4844 SH |
63 | } |
64 | ||
65 | void iothread_join(IOThread *iothread) | |
66 | { | |
67 | aio_bh_schedule_oneshot(iothread->ctx, iothread_stop_bh, iothread); | |
0c330a73 PB |
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 | ||
75 | IOThread *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 | ||
94 | AioContext *iothread_get_aio_context(IOThread *iothread) | |
95 | { | |
96 | return iothread->ctx; | |
97 | } |