root / util / qemu-thread-win32.c @ feature-archipelago
History | View | Annotate | Download (9.5 kB)
1 | 9257d46d | Paolo Bonzini | /*
|
---|---|---|---|
2 | 9257d46d | Paolo Bonzini | * Win32 implementation for mutex/cond/thread functions
|
3 | 9257d46d | Paolo Bonzini | *
|
4 | 9257d46d | Paolo Bonzini | * Copyright Red Hat, Inc. 2010
|
5 | 9257d46d | Paolo Bonzini | *
|
6 | 9257d46d | Paolo Bonzini | * Author:
|
7 | 9257d46d | Paolo Bonzini | * Paolo Bonzini <pbonzini@redhat.com>
|
8 | 9257d46d | Paolo Bonzini | *
|
9 | 9257d46d | Paolo Bonzini | * This work is licensed under the terms of the GNU GPL, version 2 or later.
|
10 | 9257d46d | Paolo Bonzini | * See the COPYING file in the top-level directory.
|
11 | 9257d46d | Paolo Bonzini | *
|
12 | 9257d46d | Paolo Bonzini | */
|
13 | 9257d46d | Paolo Bonzini | #include "qemu-common.h" |
14 | 1de7afc9 | Paolo Bonzini | #include "qemu/thread.h" |
15 | 9257d46d | Paolo Bonzini | #include <process.h> |
16 | 9257d46d | Paolo Bonzini | #include <assert.h> |
17 | 9257d46d | Paolo Bonzini | #include <limits.h> |
18 | 9257d46d | Paolo Bonzini | |
19 | 9257d46d | Paolo Bonzini | static void error_exit(int err, const char *msg) |
20 | 9257d46d | Paolo Bonzini | { |
21 | 9257d46d | Paolo Bonzini | char *pstr;
|
22 | 9257d46d | Paolo Bonzini | |
23 | 9257d46d | Paolo Bonzini | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, |
24 | 9257d46d | Paolo Bonzini | NULL, err, 0, (LPTSTR)&pstr, 2, NULL); |
25 | 9257d46d | Paolo Bonzini | fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
|
26 | 9257d46d | Paolo Bonzini | LocalFree(pstr); |
27 | 53380ac3 | Jan Kiszka | abort(); |
28 | 9257d46d | Paolo Bonzini | } |
29 | 9257d46d | Paolo Bonzini | |
30 | 9257d46d | Paolo Bonzini | void qemu_mutex_init(QemuMutex *mutex)
|
31 | 9257d46d | Paolo Bonzini | { |
32 | 9257d46d | Paolo Bonzini | mutex->owner = 0;
|
33 | 9257d46d | Paolo Bonzini | InitializeCriticalSection(&mutex->lock); |
34 | 9257d46d | Paolo Bonzini | } |
35 | 9257d46d | Paolo Bonzini | |
36 | 1a290aea | Stefan Weil | void qemu_mutex_destroy(QemuMutex *mutex)
|
37 | 1a290aea | Stefan Weil | { |
38 | 1a290aea | Stefan Weil | assert(mutex->owner == 0);
|
39 | 1a290aea | Stefan Weil | DeleteCriticalSection(&mutex->lock); |
40 | 1a290aea | Stefan Weil | } |
41 | 1a290aea | Stefan Weil | |
42 | 9257d46d | Paolo Bonzini | void qemu_mutex_lock(QemuMutex *mutex)
|
43 | 9257d46d | Paolo Bonzini | { |
44 | 9257d46d | Paolo Bonzini | EnterCriticalSection(&mutex->lock); |
45 | 9257d46d | Paolo Bonzini | |
46 | 9257d46d | Paolo Bonzini | /* Win32 CRITICAL_SECTIONs are recursive. Assert that we're not
|
47 | 9257d46d | Paolo Bonzini | * using them as such.
|
48 | 9257d46d | Paolo Bonzini | */
|
49 | 9257d46d | Paolo Bonzini | assert(mutex->owner == 0);
|
50 | 9257d46d | Paolo Bonzini | mutex->owner = GetCurrentThreadId(); |
51 | 9257d46d | Paolo Bonzini | } |
52 | 9257d46d | Paolo Bonzini | |
53 | 9257d46d | Paolo Bonzini | int qemu_mutex_trylock(QemuMutex *mutex)
|
54 | 9257d46d | Paolo Bonzini | { |
55 | 9257d46d | Paolo Bonzini | int owned;
|
56 | 9257d46d | Paolo Bonzini | |
57 | 9257d46d | Paolo Bonzini | owned = TryEnterCriticalSection(&mutex->lock); |
58 | 9257d46d | Paolo Bonzini | if (owned) {
|
59 | 9257d46d | Paolo Bonzini | assert(mutex->owner == 0);
|
60 | 9257d46d | Paolo Bonzini | mutex->owner = GetCurrentThreadId(); |
61 | 9257d46d | Paolo Bonzini | } |
62 | 9257d46d | Paolo Bonzini | return !owned;
|
63 | 9257d46d | Paolo Bonzini | } |
64 | 9257d46d | Paolo Bonzini | |
65 | 9257d46d | Paolo Bonzini | void qemu_mutex_unlock(QemuMutex *mutex)
|
66 | 9257d46d | Paolo Bonzini | { |
67 | 9257d46d | Paolo Bonzini | assert(mutex->owner == GetCurrentThreadId()); |
68 | 9257d46d | Paolo Bonzini | mutex->owner = 0;
|
69 | 9257d46d | Paolo Bonzini | LeaveCriticalSection(&mutex->lock); |
70 | 9257d46d | Paolo Bonzini | } |
71 | 9257d46d | Paolo Bonzini | |
72 | 9257d46d | Paolo Bonzini | void qemu_cond_init(QemuCond *cond)
|
73 | 9257d46d | Paolo Bonzini | { |
74 | 9257d46d | Paolo Bonzini | memset(cond, 0, sizeof(*cond)); |
75 | 9257d46d | Paolo Bonzini | |
76 | 9257d46d | Paolo Bonzini | cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL); |
77 | 9257d46d | Paolo Bonzini | if (!cond->sema) {
|
78 | 9257d46d | Paolo Bonzini | error_exit(GetLastError(), __func__); |
79 | 9257d46d | Paolo Bonzini | } |
80 | 9257d46d | Paolo Bonzini | cond->continue_event = CreateEvent(NULL, /* security */ |
81 | 9257d46d | Paolo Bonzini | FALSE, /* auto-reset */
|
82 | 9257d46d | Paolo Bonzini | FALSE, /* not signaled */
|
83 | 9257d46d | Paolo Bonzini | NULL); /* name */ |
84 | 9257d46d | Paolo Bonzini | if (!cond->continue_event) {
|
85 | 9257d46d | Paolo Bonzini | error_exit(GetLastError(), __func__); |
86 | 9257d46d | Paolo Bonzini | } |
87 | 9257d46d | Paolo Bonzini | } |
88 | 9257d46d | Paolo Bonzini | |
89 | 1a290aea | Stefan Weil | void qemu_cond_destroy(QemuCond *cond)
|
90 | 1a290aea | Stefan Weil | { |
91 | 1a290aea | Stefan Weil | BOOL result; |
92 | 1a290aea | Stefan Weil | result = CloseHandle(cond->continue_event); |
93 | 1a290aea | Stefan Weil | if (!result) {
|
94 | 1a290aea | Stefan Weil | error_exit(GetLastError(), __func__); |
95 | 1a290aea | Stefan Weil | } |
96 | 1a290aea | Stefan Weil | cond->continue_event = 0;
|
97 | 1a290aea | Stefan Weil | result = CloseHandle(cond->sema); |
98 | 1a290aea | Stefan Weil | if (!result) {
|
99 | 1a290aea | Stefan Weil | error_exit(GetLastError(), __func__); |
100 | 1a290aea | Stefan Weil | } |
101 | 1a290aea | Stefan Weil | cond->sema = 0;
|
102 | 1a290aea | Stefan Weil | } |
103 | 1a290aea | Stefan Weil | |
104 | 9257d46d | Paolo Bonzini | void qemu_cond_signal(QemuCond *cond)
|
105 | 9257d46d | Paolo Bonzini | { |
106 | 9257d46d | Paolo Bonzini | DWORD result; |
107 | 9257d46d | Paolo Bonzini | |
108 | 9257d46d | Paolo Bonzini | /*
|
109 | 9257d46d | Paolo Bonzini | * Signal only when there are waiters. cond->waiters is
|
110 | 9257d46d | Paolo Bonzini | * incremented by pthread_cond_wait under the external lock,
|
111 | 9257d46d | Paolo Bonzini | * so we are safe about that.
|
112 | 9257d46d | Paolo Bonzini | */
|
113 | 9257d46d | Paolo Bonzini | if (cond->waiters == 0) { |
114 | 9257d46d | Paolo Bonzini | return;
|
115 | 9257d46d | Paolo Bonzini | } |
116 | 9257d46d | Paolo Bonzini | |
117 | 9257d46d | Paolo Bonzini | /*
|
118 | 9257d46d | Paolo Bonzini | * Waiting threads decrement it outside the external lock, but
|
119 | 9257d46d | Paolo Bonzini | * only if another thread is executing pthread_cond_broadcast and
|
120 | 9257d46d | Paolo Bonzini | * has the mutex. So, it also cannot be decremented concurrently
|
121 | 9257d46d | Paolo Bonzini | * with this particular access.
|
122 | 9257d46d | Paolo Bonzini | */
|
123 | 9257d46d | Paolo Bonzini | cond->target = cond->waiters - 1;
|
124 | 9257d46d | Paolo Bonzini | result = SignalObjectAndWait(cond->sema, cond->continue_event, |
125 | 9257d46d | Paolo Bonzini | INFINITE, FALSE); |
126 | 9257d46d | Paolo Bonzini | if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
|
127 | 9257d46d | Paolo Bonzini | error_exit(GetLastError(), __func__); |
128 | 9257d46d | Paolo Bonzini | } |
129 | 9257d46d | Paolo Bonzini | } |
130 | 9257d46d | Paolo Bonzini | |
131 | 9257d46d | Paolo Bonzini | void qemu_cond_broadcast(QemuCond *cond)
|
132 | 9257d46d | Paolo Bonzini | { |
133 | 9257d46d | Paolo Bonzini | BOOLEAN result; |
134 | 9257d46d | Paolo Bonzini | /*
|
135 | 9257d46d | Paolo Bonzini | * As in pthread_cond_signal, access to cond->waiters and
|
136 | 9257d46d | Paolo Bonzini | * cond->target is locked via the external mutex.
|
137 | 9257d46d | Paolo Bonzini | */
|
138 | 9257d46d | Paolo Bonzini | if (cond->waiters == 0) { |
139 | 9257d46d | Paolo Bonzini | return;
|
140 | 9257d46d | Paolo Bonzini | } |
141 | 9257d46d | Paolo Bonzini | |
142 | 9257d46d | Paolo Bonzini | cond->target = 0;
|
143 | 9257d46d | Paolo Bonzini | result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
|
144 | 9257d46d | Paolo Bonzini | if (!result) {
|
145 | 9257d46d | Paolo Bonzini | error_exit(GetLastError(), __func__); |
146 | 9257d46d | Paolo Bonzini | } |
147 | 9257d46d | Paolo Bonzini | |
148 | 9257d46d | Paolo Bonzini | /*
|
149 | 9257d46d | Paolo Bonzini | * At this point all waiters continue. Each one takes its
|
150 | 9257d46d | Paolo Bonzini | * slice of the semaphore. Now it's our turn to wait: Since
|
151 | 9257d46d | Paolo Bonzini | * the external mutex is held, no thread can leave cond_wait,
|
152 | 9257d46d | Paolo Bonzini | * yet. For this reason, we can be sure that no thread gets
|
153 | 9257d46d | Paolo Bonzini | * a chance to eat *more* than one slice. OTOH, it means
|
154 | 9257d46d | Paolo Bonzini | * that the last waiter must send us a wake-up.
|
155 | 9257d46d | Paolo Bonzini | */
|
156 | 9257d46d | Paolo Bonzini | WaitForSingleObject(cond->continue_event, INFINITE); |
157 | 9257d46d | Paolo Bonzini | } |
158 | 9257d46d | Paolo Bonzini | |
159 | 9257d46d | Paolo Bonzini | void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
|
160 | 9257d46d | Paolo Bonzini | { |
161 | 9257d46d | Paolo Bonzini | /*
|
162 | 9257d46d | Paolo Bonzini | * This access is protected under the mutex.
|
163 | 9257d46d | Paolo Bonzini | */
|
164 | 9257d46d | Paolo Bonzini | cond->waiters++; |
165 | 9257d46d | Paolo Bonzini | |
166 | 9257d46d | Paolo Bonzini | /*
|
167 | 9257d46d | Paolo Bonzini | * Unlock external mutex and wait for signal.
|
168 | 9257d46d | Paolo Bonzini | * NOTE: we've held mutex locked long enough to increment
|
169 | 9257d46d | Paolo Bonzini | * waiters count above, so there's no problem with
|
170 | 9257d46d | Paolo Bonzini | * leaving mutex unlocked before we wait on semaphore.
|
171 | 9257d46d | Paolo Bonzini | */
|
172 | 9257d46d | Paolo Bonzini | qemu_mutex_unlock(mutex); |
173 | 9257d46d | Paolo Bonzini | WaitForSingleObject(cond->sema, INFINITE); |
174 | 9257d46d | Paolo Bonzini | |
175 | 9257d46d | Paolo Bonzini | /* Now waiters must rendez-vous with the signaling thread and
|
176 | 9257d46d | Paolo Bonzini | * let it continue. For cond_broadcast this has heavy contention
|
177 | 9257d46d | Paolo Bonzini | * and triggers thundering herd. So goes life.
|
178 | 9257d46d | Paolo Bonzini | *
|
179 | 9257d46d | Paolo Bonzini | * Decrease waiters count. The mutex is not taken, so we have
|
180 | 9257d46d | Paolo Bonzini | * to do this atomically.
|
181 | 9257d46d | Paolo Bonzini | *
|
182 | 9257d46d | Paolo Bonzini | * All waiters contend for the mutex at the end of this function
|
183 | 9257d46d | Paolo Bonzini | * until the signaling thread relinquishes it. To ensure
|
184 | 9257d46d | Paolo Bonzini | * each waiter consumes exactly one slice of the semaphore,
|
185 | 9257d46d | Paolo Bonzini | * the signaling thread stops until it is told by the last
|
186 | 9257d46d | Paolo Bonzini | * waiter that it can go on.
|
187 | 9257d46d | Paolo Bonzini | */
|
188 | 9257d46d | Paolo Bonzini | if (InterlockedDecrement(&cond->waiters) == cond->target) {
|
189 | 9257d46d | Paolo Bonzini | SetEvent(cond->continue_event); |
190 | 9257d46d | Paolo Bonzini | } |
191 | 9257d46d | Paolo Bonzini | |
192 | 9257d46d | Paolo Bonzini | qemu_mutex_lock(mutex); |
193 | 9257d46d | Paolo Bonzini | } |
194 | 9257d46d | Paolo Bonzini | |
195 | 38b14db3 | Paolo Bonzini | void qemu_sem_init(QemuSemaphore *sem, int init) |
196 | 38b14db3 | Paolo Bonzini | { |
197 | 38b14db3 | Paolo Bonzini | /* Manual reset. */
|
198 | 38b14db3 | Paolo Bonzini | sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL); |
199 | 38b14db3 | Paolo Bonzini | } |
200 | 38b14db3 | Paolo Bonzini | |
201 | 38b14db3 | Paolo Bonzini | void qemu_sem_destroy(QemuSemaphore *sem)
|
202 | 38b14db3 | Paolo Bonzini | { |
203 | 38b14db3 | Paolo Bonzini | CloseHandle(sem->sema); |
204 | 38b14db3 | Paolo Bonzini | } |
205 | 38b14db3 | Paolo Bonzini | |
206 | 38b14db3 | Paolo Bonzini | void qemu_sem_post(QemuSemaphore *sem)
|
207 | 38b14db3 | Paolo Bonzini | { |
208 | 38b14db3 | Paolo Bonzini | ReleaseSemaphore(sem->sema, 1, NULL); |
209 | 38b14db3 | Paolo Bonzini | } |
210 | 38b14db3 | Paolo Bonzini | |
211 | 38b14db3 | Paolo Bonzini | int qemu_sem_timedwait(QemuSemaphore *sem, int ms) |
212 | 38b14db3 | Paolo Bonzini | { |
213 | 38b14db3 | Paolo Bonzini | int rc = WaitForSingleObject(sem->sema, ms);
|
214 | 38b14db3 | Paolo Bonzini | if (rc == WAIT_OBJECT_0) {
|
215 | 38b14db3 | Paolo Bonzini | return 0; |
216 | 38b14db3 | Paolo Bonzini | } |
217 | 38b14db3 | Paolo Bonzini | if (rc != WAIT_TIMEOUT) {
|
218 | 38b14db3 | Paolo Bonzini | error_exit(GetLastError(), __func__); |
219 | 38b14db3 | Paolo Bonzini | } |
220 | 38b14db3 | Paolo Bonzini | return -1; |
221 | 38b14db3 | Paolo Bonzini | } |
222 | 38b14db3 | Paolo Bonzini | |
223 | 38b14db3 | Paolo Bonzini | void qemu_sem_wait(QemuSemaphore *sem)
|
224 | 38b14db3 | Paolo Bonzini | { |
225 | 38b14db3 | Paolo Bonzini | if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
|
226 | 38b14db3 | Paolo Bonzini | error_exit(GetLastError(), __func__); |
227 | 38b14db3 | Paolo Bonzini | } |
228 | 38b14db3 | Paolo Bonzini | } |
229 | 38b14db3 | Paolo Bonzini | |
230 | c7c4d063 | Paolo Bonzini | void qemu_event_init(QemuEvent *ev, bool init) |
231 | c7c4d063 | Paolo Bonzini | { |
232 | c7c4d063 | Paolo Bonzini | /* Manual reset. */
|
233 | c7c4d063 | Paolo Bonzini | ev->event = CreateEvent(NULL, TRUE, init, NULL); |
234 | c7c4d063 | Paolo Bonzini | } |
235 | c7c4d063 | Paolo Bonzini | |
236 | c7c4d063 | Paolo Bonzini | void qemu_event_destroy(QemuEvent *ev)
|
237 | c7c4d063 | Paolo Bonzini | { |
238 | c7c4d063 | Paolo Bonzini | CloseHandle(ev->event); |
239 | c7c4d063 | Paolo Bonzini | } |
240 | c7c4d063 | Paolo Bonzini | |
241 | c7c4d063 | Paolo Bonzini | void qemu_event_set(QemuEvent *ev)
|
242 | c7c4d063 | Paolo Bonzini | { |
243 | c7c4d063 | Paolo Bonzini | SetEvent(ev->event); |
244 | c7c4d063 | Paolo Bonzini | } |
245 | c7c4d063 | Paolo Bonzini | |
246 | c7c4d063 | Paolo Bonzini | void qemu_event_reset(QemuEvent *ev)
|
247 | c7c4d063 | Paolo Bonzini | { |
248 | c7c4d063 | Paolo Bonzini | ResetEvent(ev->event); |
249 | c7c4d063 | Paolo Bonzini | } |
250 | c7c4d063 | Paolo Bonzini | |
251 | c7c4d063 | Paolo Bonzini | void qemu_event_wait(QemuEvent *ev)
|
252 | c7c4d063 | Paolo Bonzini | { |
253 | c7c4d063 | Paolo Bonzini | WaitForSingleObject(ev->event, INFINITE); |
254 | c7c4d063 | Paolo Bonzini | } |
255 | c7c4d063 | Paolo Bonzini | |
256 | 9257d46d | Paolo Bonzini | struct QemuThreadData {
|
257 | 403e6331 | Paolo Bonzini | /* Passed to win32_start_routine. */
|
258 | 403e6331 | Paolo Bonzini | void *(*start_routine)(void *); |
259 | 403e6331 | Paolo Bonzini | void *arg;
|
260 | 403e6331 | Paolo Bonzini | short mode;
|
261 | 403e6331 | Paolo Bonzini | |
262 | 403e6331 | Paolo Bonzini | /* Only used for joinable threads. */
|
263 | 403e6331 | Paolo Bonzini | bool exited;
|
264 | 403e6331 | Paolo Bonzini | void *ret;
|
265 | 403e6331 | Paolo Bonzini | CRITICAL_SECTION cs; |
266 | 9257d46d | Paolo Bonzini | }; |
267 | 9257d46d | Paolo Bonzini | |
268 | 6265e4ff | Jan Kiszka | static __thread QemuThreadData *qemu_thread_data;
|
269 | 9257d46d | Paolo Bonzini | |
270 | 9257d46d | Paolo Bonzini | static unsigned __stdcall win32_start_routine(void *arg) |
271 | 9257d46d | Paolo Bonzini | { |
272 | 403e6331 | Paolo Bonzini | QemuThreadData *data = (QemuThreadData *) arg; |
273 | 403e6331 | Paolo Bonzini | void *(*start_routine)(void *) = data->start_routine; |
274 | 403e6331 | Paolo Bonzini | void *thread_arg = data->arg;
|
275 | 403e6331 | Paolo Bonzini | |
276 | 403e6331 | Paolo Bonzini | if (data->mode == QEMU_THREAD_DETACHED) {
|
277 | 403e6331 | Paolo Bonzini | g_free(data); |
278 | 403e6331 | Paolo Bonzini | data = NULL;
|
279 | 403e6331 | Paolo Bonzini | } |
280 | 6265e4ff | Jan Kiszka | qemu_thread_data = data; |
281 | 403e6331 | Paolo Bonzini | qemu_thread_exit(start_routine(thread_arg)); |
282 | 9257d46d | Paolo Bonzini | abort(); |
283 | 9257d46d | Paolo Bonzini | } |
284 | 9257d46d | Paolo Bonzini | |
285 | 9257d46d | Paolo Bonzini | void qemu_thread_exit(void *arg) |
286 | 9257d46d | Paolo Bonzini | { |
287 | 6265e4ff | Jan Kiszka | QemuThreadData *data = qemu_thread_data; |
288 | 6265e4ff | Jan Kiszka | |
289 | 403e6331 | Paolo Bonzini | if (data) {
|
290 | edc1de97 | Stefan Weil | assert(data->mode != QEMU_THREAD_DETACHED); |
291 | 403e6331 | Paolo Bonzini | data->ret = arg; |
292 | 403e6331 | Paolo Bonzini | EnterCriticalSection(&data->cs); |
293 | 403e6331 | Paolo Bonzini | data->exited = true;
|
294 | 403e6331 | Paolo Bonzini | LeaveCriticalSection(&data->cs); |
295 | 403e6331 | Paolo Bonzini | } |
296 | 403e6331 | Paolo Bonzini | _endthreadex(0);
|
297 | 403e6331 | Paolo Bonzini | } |
298 | 403e6331 | Paolo Bonzini | |
299 | 403e6331 | Paolo Bonzini | void *qemu_thread_join(QemuThread *thread)
|
300 | 403e6331 | Paolo Bonzini | { |
301 | 403e6331 | Paolo Bonzini | QemuThreadData *data; |
302 | 403e6331 | Paolo Bonzini | void *ret;
|
303 | 403e6331 | Paolo Bonzini | HANDLE handle; |
304 | 403e6331 | Paolo Bonzini | |
305 | 403e6331 | Paolo Bonzini | data = thread->data; |
306 | 403e6331 | Paolo Bonzini | if (!data) {
|
307 | 403e6331 | Paolo Bonzini | return NULL; |
308 | 403e6331 | Paolo Bonzini | } |
309 | 403e6331 | Paolo Bonzini | /*
|
310 | 403e6331 | Paolo Bonzini | * Because multiple copies of the QemuThread can exist via
|
311 | 403e6331 | Paolo Bonzini | * qemu_thread_get_self, we need to store a value that cannot
|
312 | 403e6331 | Paolo Bonzini | * leak there. The simplest, non racy way is to store the TID,
|
313 | 403e6331 | Paolo Bonzini | * discard the handle that _beginthreadex gives back, and
|
314 | 403e6331 | Paolo Bonzini | * get another copy of the handle here.
|
315 | 403e6331 | Paolo Bonzini | */
|
316 | 1ecf47bf | Paolo Bonzini | handle = qemu_thread_get_handle(thread); |
317 | 1ecf47bf | Paolo Bonzini | if (handle) {
|
318 | 403e6331 | Paolo Bonzini | WaitForSingleObject(handle, INFINITE); |
319 | 403e6331 | Paolo Bonzini | CloseHandle(handle); |
320 | 403e6331 | Paolo Bonzini | } |
321 | 403e6331 | Paolo Bonzini | ret = data->ret; |
322 | edc1de97 | Stefan Weil | assert(data->mode != QEMU_THREAD_DETACHED); |
323 | 403e6331 | Paolo Bonzini | DeleteCriticalSection(&data->cs); |
324 | 403e6331 | Paolo Bonzini | g_free(data); |
325 | 403e6331 | Paolo Bonzini | return ret;
|
326 | 9257d46d | Paolo Bonzini | } |
327 | 9257d46d | Paolo Bonzini | |
328 | 9257d46d | Paolo Bonzini | void qemu_thread_create(QemuThread *thread,
|
329 | 9257d46d | Paolo Bonzini | void *(*start_routine)(void *), |
330 | cf218714 | Jan Kiszka | void *arg, int mode) |
331 | 9257d46d | Paolo Bonzini | { |
332 | 9257d46d | Paolo Bonzini | HANDLE hThread; |
333 | 9257d46d | Paolo Bonzini | struct QemuThreadData *data;
|
334 | 6265e4ff | Jan Kiszka | |
335 | 7267c094 | Anthony Liguori | data = g_malloc(sizeof *data);
|
336 | 9257d46d | Paolo Bonzini | data->start_routine = start_routine; |
337 | 9257d46d | Paolo Bonzini | data->arg = arg; |
338 | 403e6331 | Paolo Bonzini | data->mode = mode; |
339 | 403e6331 | Paolo Bonzini | data->exited = false;
|
340 | 9257d46d | Paolo Bonzini | |
341 | edc1de97 | Stefan Weil | if (data->mode != QEMU_THREAD_DETACHED) {
|
342 | edc1de97 | Stefan Weil | InitializeCriticalSection(&data->cs); |
343 | edc1de97 | Stefan Weil | } |
344 | edc1de97 | Stefan Weil | |
345 | 9257d46d | Paolo Bonzini | hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine, |
346 | 403e6331 | Paolo Bonzini | data, 0, &thread->tid);
|
347 | 9257d46d | Paolo Bonzini | if (!hThread) {
|
348 | 9257d46d | Paolo Bonzini | error_exit(GetLastError(), __func__); |
349 | 9257d46d | Paolo Bonzini | } |
350 | 9257d46d | Paolo Bonzini | CloseHandle(hThread); |
351 | 403e6331 | Paolo Bonzini | thread->data = (mode == QEMU_THREAD_DETACHED) ? NULL : data;
|
352 | 9257d46d | Paolo Bonzini | } |
353 | 9257d46d | Paolo Bonzini | |
354 | 9257d46d | Paolo Bonzini | void qemu_thread_get_self(QemuThread *thread)
|
355 | 9257d46d | Paolo Bonzini | { |
356 | 6265e4ff | Jan Kiszka | thread->data = qemu_thread_data; |
357 | 403e6331 | Paolo Bonzini | thread->tid = GetCurrentThreadId(); |
358 | 9257d46d | Paolo Bonzini | } |
359 | 9257d46d | Paolo Bonzini | |
360 | 1ecf47bf | Paolo Bonzini | HANDLE qemu_thread_get_handle(QemuThread *thread) |
361 | 1ecf47bf | Paolo Bonzini | { |
362 | 1ecf47bf | Paolo Bonzini | QemuThreadData *data; |
363 | 1ecf47bf | Paolo Bonzini | HANDLE handle; |
364 | 1ecf47bf | Paolo Bonzini | |
365 | 1ecf47bf | Paolo Bonzini | data = thread->data; |
366 | 1ecf47bf | Paolo Bonzini | if (!data) {
|
367 | 1ecf47bf | Paolo Bonzini | return NULL; |
368 | 1ecf47bf | Paolo Bonzini | } |
369 | 1ecf47bf | Paolo Bonzini | |
370 | edc1de97 | Stefan Weil | assert(data->mode != QEMU_THREAD_DETACHED); |
371 | 1ecf47bf | Paolo Bonzini | EnterCriticalSection(&data->cs); |
372 | 1ecf47bf | Paolo Bonzini | if (!data->exited) {
|
373 | 1ecf47bf | Paolo Bonzini | handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE, |
374 | 1ecf47bf | Paolo Bonzini | thread->tid); |
375 | 1ecf47bf | Paolo Bonzini | } else {
|
376 | 1ecf47bf | Paolo Bonzini | handle = NULL;
|
377 | 1ecf47bf | Paolo Bonzini | } |
378 | 1ecf47bf | Paolo Bonzini | LeaveCriticalSection(&data->cs); |
379 | 1ecf47bf | Paolo Bonzini | return handle;
|
380 | 1ecf47bf | Paolo Bonzini | } |
381 | 1ecf47bf | Paolo Bonzini | |
382 | 2d797b65 | Andreas Färber | bool qemu_thread_is_self(QemuThread *thread)
|
383 | 9257d46d | Paolo Bonzini | { |
384 | 403e6331 | Paolo Bonzini | return GetCurrentThreadId() == thread->tid;
|
385 | 9257d46d | Paolo Bonzini | } |