xref: /openbmc/qemu/util/qemu-thread-win32.c (revision 56411125)
1 /*
2  * Win32 implementation for mutex/cond/thread functions
3  *
4  * Copyright Red Hat, Inc. 2010
5  *
6  * Author:
7  *  Paolo Bonzini <pbonzini@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  *
12  */
13 #include "qemu-common.h"
14 #include "qemu/thread.h"
15 #include "qemu/notify.h"
16 #include <process.h>
17 #include <assert.h>
18 #include <limits.h>
19 
20 static bool name_threads;
21 
22 void qemu_thread_naming(bool enable)
23 {
24     /* But note we don't actually name them on Windows yet */
25     name_threads = enable;
26 
27     fprintf(stderr, "qemu: thread naming not supported on this host\n");
28 }
29 
30 static void error_exit(int err, const char *msg)
31 {
32     char *pstr;
33 
34     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
35                   NULL, err, 0, (LPTSTR)&pstr, 2, NULL);
36     fprintf(stderr, "qemu: %s: %s\n", msg, pstr);
37     LocalFree(pstr);
38     abort();
39 }
40 
41 void qemu_mutex_init(QemuMutex *mutex)
42 {
43     mutex->owner = 0;
44     InitializeCriticalSection(&mutex->lock);
45 }
46 
47 void qemu_mutex_destroy(QemuMutex *mutex)
48 {
49     assert(mutex->owner == 0);
50     DeleteCriticalSection(&mutex->lock);
51 }
52 
53 void qemu_mutex_lock(QemuMutex *mutex)
54 {
55     EnterCriticalSection(&mutex->lock);
56 
57     /* Win32 CRITICAL_SECTIONs are recursive.  Assert that we're not
58      * using them as such.
59      */
60     assert(mutex->owner == 0);
61     mutex->owner = GetCurrentThreadId();
62 }
63 
64 int qemu_mutex_trylock(QemuMutex *mutex)
65 {
66     int owned;
67 
68     owned = TryEnterCriticalSection(&mutex->lock);
69     if (owned) {
70         assert(mutex->owner == 0);
71         mutex->owner = GetCurrentThreadId();
72     }
73     return !owned;
74 }
75 
76 void qemu_mutex_unlock(QemuMutex *mutex)
77 {
78     assert(mutex->owner == GetCurrentThreadId());
79     mutex->owner = 0;
80     LeaveCriticalSection(&mutex->lock);
81 }
82 
83 void qemu_cond_init(QemuCond *cond)
84 {
85     memset(cond, 0, sizeof(*cond));
86 
87     cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
88     if (!cond->sema) {
89         error_exit(GetLastError(), __func__);
90     }
91     cond->continue_event = CreateEvent(NULL,    /* security */
92                                        FALSE,   /* auto-reset */
93                                        FALSE,   /* not signaled */
94                                        NULL);   /* name */
95     if (!cond->continue_event) {
96         error_exit(GetLastError(), __func__);
97     }
98 }
99 
100 void qemu_cond_destroy(QemuCond *cond)
101 {
102     BOOL result;
103     result = CloseHandle(cond->continue_event);
104     if (!result) {
105         error_exit(GetLastError(), __func__);
106     }
107     cond->continue_event = 0;
108     result = CloseHandle(cond->sema);
109     if (!result) {
110         error_exit(GetLastError(), __func__);
111     }
112     cond->sema = 0;
113 }
114 
115 void qemu_cond_signal(QemuCond *cond)
116 {
117     DWORD result;
118 
119     /*
120      * Signal only when there are waiters.  cond->waiters is
121      * incremented by pthread_cond_wait under the external lock,
122      * so we are safe about that.
123      */
124     if (cond->waiters == 0) {
125         return;
126     }
127 
128     /*
129      * Waiting threads decrement it outside the external lock, but
130      * only if another thread is executing pthread_cond_broadcast and
131      * has the mutex.  So, it also cannot be decremented concurrently
132      * with this particular access.
133      */
134     cond->target = cond->waiters - 1;
135     result = SignalObjectAndWait(cond->sema, cond->continue_event,
136                                  INFINITE, FALSE);
137     if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
138         error_exit(GetLastError(), __func__);
139     }
140 }
141 
142 void qemu_cond_broadcast(QemuCond *cond)
143 {
144     BOOLEAN result;
145     /*
146      * As in pthread_cond_signal, access to cond->waiters and
147      * cond->target is locked via the external mutex.
148      */
149     if (cond->waiters == 0) {
150         return;
151     }
152 
153     cond->target = 0;
154     result = ReleaseSemaphore(cond->sema, cond->waiters, NULL);
155     if (!result) {
156         error_exit(GetLastError(), __func__);
157     }
158 
159     /*
160      * At this point all waiters continue. Each one takes its
161      * slice of the semaphore. Now it's our turn to wait: Since
162      * the external mutex is held, no thread can leave cond_wait,
163      * yet. For this reason, we can be sure that no thread gets
164      * a chance to eat *more* than one slice. OTOH, it means
165      * that the last waiter must send us a wake-up.
166      */
167     WaitForSingleObject(cond->continue_event, INFINITE);
168 }
169 
170 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex)
171 {
172     /*
173      * This access is protected under the mutex.
174      */
175     cond->waiters++;
176 
177     /*
178      * Unlock external mutex and wait for signal.
179      * NOTE: we've held mutex locked long enough to increment
180      * waiters count above, so there's no problem with
181      * leaving mutex unlocked before we wait on semaphore.
182      */
183     qemu_mutex_unlock(mutex);
184     WaitForSingleObject(cond->sema, INFINITE);
185 
186     /* Now waiters must rendez-vous with the signaling thread and
187      * let it continue.  For cond_broadcast this has heavy contention
188      * and triggers thundering herd.  So goes life.
189      *
190      * Decrease waiters count.  The mutex is not taken, so we have
191      * to do this atomically.
192      *
193      * All waiters contend for the mutex at the end of this function
194      * until the signaling thread relinquishes it.  To ensure
195      * each waiter consumes exactly one slice of the semaphore,
196      * the signaling thread stops until it is told by the last
197      * waiter that it can go on.
198      */
199     if (InterlockedDecrement(&cond->waiters) == cond->target) {
200         SetEvent(cond->continue_event);
201     }
202 
203     qemu_mutex_lock(mutex);
204 }
205 
206 void qemu_sem_init(QemuSemaphore *sem, int init)
207 {
208     /* Manual reset.  */
209     sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL);
210 }
211 
212 void qemu_sem_destroy(QemuSemaphore *sem)
213 {
214     CloseHandle(sem->sema);
215 }
216 
217 void qemu_sem_post(QemuSemaphore *sem)
218 {
219     ReleaseSemaphore(sem->sema, 1, NULL);
220 }
221 
222 int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
223 {
224     int rc = WaitForSingleObject(sem->sema, ms);
225     if (rc == WAIT_OBJECT_0) {
226         return 0;
227     }
228     if (rc != WAIT_TIMEOUT) {
229         error_exit(GetLastError(), __func__);
230     }
231     return -1;
232 }
233 
234 void qemu_sem_wait(QemuSemaphore *sem)
235 {
236     if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) {
237         error_exit(GetLastError(), __func__);
238     }
239 }
240 
241 /* Wrap a Win32 manual-reset event with a fast userspace path.  The idea
242  * is to reset the Win32 event lazily, as part of a test-reset-test-wait
243  * sequence.  Such a sequence is, indeed, how QemuEvents are used by
244  * RCU and other subsystems!
245  *
246  * Valid transitions:
247  * - free->set, when setting the event
248  * - busy->set, when setting the event, followed by futex_wake
249  * - set->free, when resetting the event
250  * - free->busy, when waiting
251  *
252  * set->busy does not happen (it can be observed from the outside but
253  * it really is set->free->busy).
254  *
255  * busy->free provably cannot happen; to enforce it, the set->free transition
256  * is done with an OR, which becomes a no-op if the event has concurrently
257  * transitioned to free or busy (and is faster than cmpxchg).
258  */
259 
260 #define EV_SET         0
261 #define EV_FREE        1
262 #define EV_BUSY       -1
263 
264 void qemu_event_init(QemuEvent *ev, bool init)
265 {
266     /* Manual reset.  */
267     ev->event = CreateEvent(NULL, TRUE, TRUE, NULL);
268     ev->value = (init ? EV_SET : EV_FREE);
269 }
270 
271 void qemu_event_destroy(QemuEvent *ev)
272 {
273     CloseHandle(ev->event);
274 }
275 
276 void qemu_event_set(QemuEvent *ev)
277 {
278     if (atomic_mb_read(&ev->value) != EV_SET) {
279         if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
280             /* There were waiters, wake them up.  */
281             SetEvent(ev->event);
282         }
283     }
284 }
285 
286 void qemu_event_reset(QemuEvent *ev)
287 {
288     if (atomic_mb_read(&ev->value) == EV_SET) {
289         /* If there was a concurrent reset (or even reset+wait),
290          * do nothing.  Otherwise change EV_SET->EV_FREE.
291          */
292         atomic_or(&ev->value, EV_FREE);
293     }
294 }
295 
296 void qemu_event_wait(QemuEvent *ev)
297 {
298     unsigned value;
299 
300     value = atomic_mb_read(&ev->value);
301     if (value != EV_SET) {
302         if (value == EV_FREE) {
303             /* qemu_event_set is not yet going to call SetEvent, but we are
304              * going to do another check for EV_SET below when setting EV_BUSY.
305              * At that point it is safe to call WaitForSingleObject.
306              */
307             ResetEvent(ev->event);
308 
309             /* Tell qemu_event_set that there are waiters.  No need to retry
310              * because there cannot be a concurent busy->free transition.
311              * After the CAS, the event will be either set or busy.
312              */
313             if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) {
314                 value = EV_SET;
315             } else {
316                 value = EV_BUSY;
317             }
318         }
319         if (value == EV_BUSY) {
320             WaitForSingleObject(ev->event, INFINITE);
321         }
322     }
323 }
324 
325 struct QemuThreadData {
326     /* Passed to win32_start_routine.  */
327     void             *(*start_routine)(void *);
328     void             *arg;
329     short             mode;
330     NotifierList      exit;
331 
332     /* Only used for joinable threads. */
333     bool              exited;
334     void             *ret;
335     CRITICAL_SECTION  cs;
336 };
337 
338 static bool atexit_registered;
339 static NotifierList main_thread_exit;
340 
341 static __thread QemuThreadData *qemu_thread_data;
342 
343 static void run_main_thread_exit(void)
344 {
345     notifier_list_notify(&main_thread_exit, NULL);
346 }
347 
348 void qemu_thread_atexit_add(Notifier *notifier)
349 {
350     if (!qemu_thread_data) {
351         if (!atexit_registered) {
352             atexit_registered = true;
353             atexit(run_main_thread_exit);
354         }
355         notifier_list_add(&main_thread_exit, notifier);
356     } else {
357         notifier_list_add(&qemu_thread_data->exit, notifier);
358     }
359 }
360 
361 void qemu_thread_atexit_remove(Notifier *notifier)
362 {
363     notifier_remove(notifier);
364 }
365 
366 static unsigned __stdcall win32_start_routine(void *arg)
367 {
368     QemuThreadData *data = (QemuThreadData *) arg;
369     void *(*start_routine)(void *) = data->start_routine;
370     void *thread_arg = data->arg;
371 
372     qemu_thread_data = data;
373     qemu_thread_exit(start_routine(thread_arg));
374     abort();
375 }
376 
377 void qemu_thread_exit(void *arg)
378 {
379     QemuThreadData *data = qemu_thread_data;
380 
381     notifier_list_notify(&data->exit, NULL);
382     if (data->mode == QEMU_THREAD_JOINABLE) {
383         data->ret = arg;
384         EnterCriticalSection(&data->cs);
385         data->exited = true;
386         LeaveCriticalSection(&data->cs);
387     } else {
388         g_free(data);
389     }
390     _endthreadex(0);
391 }
392 
393 void *qemu_thread_join(QemuThread *thread)
394 {
395     QemuThreadData *data;
396     void *ret;
397     HANDLE handle;
398 
399     data = thread->data;
400     if (data->mode == QEMU_THREAD_DETACHED) {
401         return NULL;
402     }
403 
404     /*
405      * Because multiple copies of the QemuThread can exist via
406      * qemu_thread_get_self, we need to store a value that cannot
407      * leak there.  The simplest, non racy way is to store the TID,
408      * discard the handle that _beginthreadex gives back, and
409      * get another copy of the handle here.
410      */
411     handle = qemu_thread_get_handle(thread);
412     if (handle) {
413         WaitForSingleObject(handle, INFINITE);
414         CloseHandle(handle);
415     }
416     ret = data->ret;
417     DeleteCriticalSection(&data->cs);
418     g_free(data);
419     return ret;
420 }
421 
422 void qemu_thread_create(QemuThread *thread, const char *name,
423                        void *(*start_routine)(void *),
424                        void *arg, int mode)
425 {
426     HANDLE hThread;
427     struct QemuThreadData *data;
428 
429     data = g_malloc(sizeof *data);
430     data->start_routine = start_routine;
431     data->arg = arg;
432     data->mode = mode;
433     data->exited = false;
434     notifier_list_init(&data->exit);
435 
436     if (data->mode != QEMU_THREAD_DETACHED) {
437         InitializeCriticalSection(&data->cs);
438     }
439 
440     hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine,
441                                       data, 0, &thread->tid);
442     if (!hThread) {
443         error_exit(GetLastError(), __func__);
444     }
445     CloseHandle(hThread);
446     thread->data = data;
447 }
448 
449 void qemu_thread_get_self(QemuThread *thread)
450 {
451     thread->data = qemu_thread_data;
452     thread->tid = GetCurrentThreadId();
453 }
454 
455 HANDLE qemu_thread_get_handle(QemuThread *thread)
456 {
457     QemuThreadData *data;
458     HANDLE handle;
459 
460     data = thread->data;
461     if (data->mode == QEMU_THREAD_DETACHED) {
462         return NULL;
463     }
464 
465     EnterCriticalSection(&data->cs);
466     if (!data->exited) {
467         handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE,
468                             thread->tid);
469     } else {
470         handle = NULL;
471     }
472     LeaveCriticalSection(&data->cs);
473     return handle;
474 }
475 
476 bool qemu_thread_is_self(QemuThread *thread)
477 {
478     return GetCurrentThreadId() == thread->tid;
479 }
480