1baacf047SPaolo Bonzini /* 2baacf047SPaolo Bonzini * Win32 implementation for mutex/cond/thread functions 3baacf047SPaolo Bonzini * 4baacf047SPaolo Bonzini * Copyright Red Hat, Inc. 2010 5baacf047SPaolo Bonzini * 6baacf047SPaolo Bonzini * Author: 7baacf047SPaolo Bonzini * Paolo Bonzini <pbonzini@redhat.com> 8baacf047SPaolo Bonzini * 9baacf047SPaolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2 or later. 10baacf047SPaolo Bonzini * See the COPYING file in the top-level directory. 11baacf047SPaolo Bonzini * 12baacf047SPaolo Bonzini */ 1312f8def0SAndrey Shedel 14aafd7584SPeter Maydell #include "qemu/osdep.h" 15baacf047SPaolo Bonzini #include "qemu-common.h" 16baacf047SPaolo Bonzini #include "qemu/thread.h" 17ef57137fSPaolo Bonzini #include "qemu/notify.h" 18f1aff7aaSPeter Xu #include "qemu-thread-common.h" 19baacf047SPaolo Bonzini #include <process.h> 20baacf047SPaolo Bonzini 218f480de0SDr. David Alan Gilbert static bool name_threads; 228f480de0SDr. David Alan Gilbert 238f480de0SDr. David Alan Gilbert void qemu_thread_naming(bool enable) 248f480de0SDr. David Alan Gilbert { 258f480de0SDr. David Alan Gilbert /* But note we don't actually name them on Windows yet */ 268f480de0SDr. David Alan Gilbert name_threads = enable; 275c312079SDr. David Alan Gilbert 285c312079SDr. David Alan Gilbert fprintf(stderr, "qemu: thread naming not supported on this host\n"); 298f480de0SDr. David Alan Gilbert } 308f480de0SDr. David Alan Gilbert 31baacf047SPaolo Bonzini static void error_exit(int err, const char *msg) 32baacf047SPaolo Bonzini { 33baacf047SPaolo Bonzini char *pstr; 34baacf047SPaolo Bonzini 35baacf047SPaolo Bonzini FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 36baacf047SPaolo Bonzini NULL, err, 0, (LPTSTR)&pstr, 2, NULL); 37baacf047SPaolo Bonzini fprintf(stderr, "qemu: %s: %s\n", msg, pstr); 38baacf047SPaolo Bonzini LocalFree(pstr); 39baacf047SPaolo Bonzini abort(); 40baacf047SPaolo Bonzini } 41baacf047SPaolo Bonzini 42baacf047SPaolo Bonzini void qemu_mutex_init(QemuMutex *mutex) 43baacf047SPaolo Bonzini { 4412f8def0SAndrey Shedel InitializeSRWLock(&mutex->lock); 45f1aff7aaSPeter Xu qemu_mutex_post_init(mutex); 46baacf047SPaolo Bonzini } 47baacf047SPaolo Bonzini 48baacf047SPaolo Bonzini void qemu_mutex_destroy(QemuMutex *mutex) 49baacf047SPaolo Bonzini { 50c096358eSFam Zheng assert(mutex->initialized); 51c096358eSFam Zheng mutex->initialized = false; 5212f8def0SAndrey Shedel InitializeSRWLock(&mutex->lock); 53baacf047SPaolo Bonzini } 54baacf047SPaolo Bonzini 556c27a0deSAlex Bennée void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line) 56baacf047SPaolo Bonzini { 57c096358eSFam Zheng assert(mutex->initialized); 58f1aff7aaSPeter Xu qemu_mutex_pre_lock(mutex, file, line); 5912f8def0SAndrey Shedel AcquireSRWLockExclusive(&mutex->lock); 60f1aff7aaSPeter Xu qemu_mutex_post_lock(mutex, file, line); 61baacf047SPaolo Bonzini } 62baacf047SPaolo Bonzini 636c27a0deSAlex Bennée int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line) 64baacf047SPaolo Bonzini { 65baacf047SPaolo Bonzini int owned; 66baacf047SPaolo Bonzini 67c096358eSFam Zheng assert(mutex->initialized); 6812f8def0SAndrey Shedel owned = TryAcquireSRWLockExclusive(&mutex->lock); 6931f5a726SJose Ricardo Ziviani if (owned) { 70f1aff7aaSPeter Xu qemu_mutex_post_lock(mutex, file, line); 7131f5a726SJose Ricardo Ziviani return 0; 7231f5a726SJose Ricardo Ziviani } 7331f5a726SJose Ricardo Ziviani return -EBUSY; 74baacf047SPaolo Bonzini } 75baacf047SPaolo Bonzini 766c27a0deSAlex Bennée void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line) 77baacf047SPaolo Bonzini { 78c096358eSFam Zheng assert(mutex->initialized); 79f1aff7aaSPeter Xu qemu_mutex_pre_unlock(mutex, file, line); 8012f8def0SAndrey Shedel ReleaseSRWLockExclusive(&mutex->lock); 81baacf047SPaolo Bonzini } 82baacf047SPaolo Bonzini 83feadec63SPaolo Bonzini void qemu_rec_mutex_init(QemuRecMutex *mutex) 84feadec63SPaolo Bonzini { 85feadec63SPaolo Bonzini InitializeCriticalSection(&mutex->lock); 86c096358eSFam Zheng mutex->initialized = true; 87feadec63SPaolo Bonzini } 88feadec63SPaolo Bonzini 89feadec63SPaolo Bonzini void qemu_rec_mutex_destroy(QemuRecMutex *mutex) 90feadec63SPaolo Bonzini { 91c096358eSFam Zheng assert(mutex->initialized); 92c096358eSFam Zheng mutex->initialized = false; 93feadec63SPaolo Bonzini DeleteCriticalSection(&mutex->lock); 94feadec63SPaolo Bonzini } 95feadec63SPaolo Bonzini 96fe9959a2SEmilio G. Cota void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line) 97feadec63SPaolo Bonzini { 98c096358eSFam Zheng assert(mutex->initialized); 99feadec63SPaolo Bonzini EnterCriticalSection(&mutex->lock); 100feadec63SPaolo Bonzini } 101feadec63SPaolo Bonzini 102fe9959a2SEmilio G. Cota int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file, int line) 103feadec63SPaolo Bonzini { 104c096358eSFam Zheng assert(mutex->initialized); 105feadec63SPaolo Bonzini return !TryEnterCriticalSection(&mutex->lock); 106feadec63SPaolo Bonzini } 107feadec63SPaolo Bonzini 108*9c75bae7SRichard Henderson void qemu_rec_mutex_unlock_impl(QemuRecMutex *mutex, const char *file, int line) 109feadec63SPaolo Bonzini { 110c096358eSFam Zheng assert(mutex->initialized); 111feadec63SPaolo Bonzini LeaveCriticalSection(&mutex->lock); 112feadec63SPaolo Bonzini } 113feadec63SPaolo Bonzini 114baacf047SPaolo Bonzini void qemu_cond_init(QemuCond *cond) 115baacf047SPaolo Bonzini { 116baacf047SPaolo Bonzini memset(cond, 0, sizeof(*cond)); 11712f8def0SAndrey Shedel InitializeConditionVariable(&cond->var); 118c096358eSFam Zheng cond->initialized = true; 119baacf047SPaolo Bonzini } 120baacf047SPaolo Bonzini 121baacf047SPaolo Bonzini void qemu_cond_destroy(QemuCond *cond) 122baacf047SPaolo Bonzini { 123c096358eSFam Zheng assert(cond->initialized); 124c096358eSFam Zheng cond->initialized = false; 12512f8def0SAndrey Shedel InitializeConditionVariable(&cond->var); 126baacf047SPaolo Bonzini } 127baacf047SPaolo Bonzini 128baacf047SPaolo Bonzini void qemu_cond_signal(QemuCond *cond) 129baacf047SPaolo Bonzini { 130c096358eSFam Zheng assert(cond->initialized); 13112f8def0SAndrey Shedel WakeConditionVariable(&cond->var); 132baacf047SPaolo Bonzini } 133baacf047SPaolo Bonzini 134baacf047SPaolo Bonzini void qemu_cond_broadcast(QemuCond *cond) 135baacf047SPaolo Bonzini { 136c096358eSFam Zheng assert(cond->initialized); 13712f8def0SAndrey Shedel WakeAllConditionVariable(&cond->var); 138baacf047SPaolo Bonzini } 139baacf047SPaolo Bonzini 1406c27a0deSAlex Bennée void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line) 141baacf047SPaolo Bonzini { 142c096358eSFam Zheng assert(cond->initialized); 143f1aff7aaSPeter Xu qemu_mutex_pre_unlock(mutex, file, line); 14412f8def0SAndrey Shedel SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0); 145f1aff7aaSPeter Xu qemu_mutex_post_lock(mutex, file, line); 146baacf047SPaolo Bonzini } 147baacf047SPaolo Bonzini 1483dcc9c6eSYury Kotov bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, 1493dcc9c6eSYury Kotov const char *file, const int line) 1503dcc9c6eSYury Kotov { 1513dcc9c6eSYury Kotov int rc = 0; 1523dcc9c6eSYury Kotov 1533dcc9c6eSYury Kotov assert(cond->initialized); 1543dcc9c6eSYury Kotov trace_qemu_mutex_unlock(mutex, file, line); 1553dcc9c6eSYury Kotov if (!SleepConditionVariableSRW(&cond->var, &mutex->lock, ms, 0)) { 1563dcc9c6eSYury Kotov rc = GetLastError(); 1573dcc9c6eSYury Kotov } 1583dcc9c6eSYury Kotov trace_qemu_mutex_locked(mutex, file, line); 1593dcc9c6eSYury Kotov if (rc && rc != ERROR_TIMEOUT) { 1603dcc9c6eSYury Kotov error_exit(rc, __func__); 1613dcc9c6eSYury Kotov } 1623dcc9c6eSYury Kotov return rc != ERROR_TIMEOUT; 1633dcc9c6eSYury Kotov } 1643dcc9c6eSYury Kotov 165baacf047SPaolo Bonzini void qemu_sem_init(QemuSemaphore *sem, int init) 166baacf047SPaolo Bonzini { 167baacf047SPaolo Bonzini /* Manual reset. */ 168baacf047SPaolo Bonzini sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL); 169c096358eSFam Zheng sem->initialized = true; 170baacf047SPaolo Bonzini } 171baacf047SPaolo Bonzini 172baacf047SPaolo Bonzini void qemu_sem_destroy(QemuSemaphore *sem) 173baacf047SPaolo Bonzini { 174c096358eSFam Zheng assert(sem->initialized); 175c096358eSFam Zheng sem->initialized = false; 176baacf047SPaolo Bonzini CloseHandle(sem->sema); 177baacf047SPaolo Bonzini } 178baacf047SPaolo Bonzini 179baacf047SPaolo Bonzini void qemu_sem_post(QemuSemaphore *sem) 180baacf047SPaolo Bonzini { 181c096358eSFam Zheng assert(sem->initialized); 182baacf047SPaolo Bonzini ReleaseSemaphore(sem->sema, 1, NULL); 183baacf047SPaolo Bonzini } 184baacf047SPaolo Bonzini 185baacf047SPaolo Bonzini int qemu_sem_timedwait(QemuSemaphore *sem, int ms) 186baacf047SPaolo Bonzini { 187c096358eSFam Zheng int rc; 188c096358eSFam Zheng 189c096358eSFam Zheng assert(sem->initialized); 190c096358eSFam Zheng rc = WaitForSingleObject(sem->sema, ms); 191baacf047SPaolo Bonzini if (rc == WAIT_OBJECT_0) { 192baacf047SPaolo Bonzini return 0; 193baacf047SPaolo Bonzini } 194baacf047SPaolo Bonzini if (rc != WAIT_TIMEOUT) { 195baacf047SPaolo Bonzini error_exit(GetLastError(), __func__); 196baacf047SPaolo Bonzini } 197baacf047SPaolo Bonzini return -1; 198baacf047SPaolo Bonzini } 199baacf047SPaolo Bonzini 200baacf047SPaolo Bonzini void qemu_sem_wait(QemuSemaphore *sem) 201baacf047SPaolo Bonzini { 202c096358eSFam Zheng assert(sem->initialized); 203baacf047SPaolo Bonzini if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) { 204baacf047SPaolo Bonzini error_exit(GetLastError(), __func__); 205baacf047SPaolo Bonzini } 206baacf047SPaolo Bonzini } 207baacf047SPaolo Bonzini 2087c9b2bf6SPaolo Bonzini /* Wrap a Win32 manual-reset event with a fast userspace path. The idea 2097c9b2bf6SPaolo Bonzini * is to reset the Win32 event lazily, as part of a test-reset-test-wait 2107c9b2bf6SPaolo Bonzini * sequence. Such a sequence is, indeed, how QemuEvents are used by 2117c9b2bf6SPaolo Bonzini * RCU and other subsystems! 2127c9b2bf6SPaolo Bonzini * 2137c9b2bf6SPaolo Bonzini * Valid transitions: 2147c9b2bf6SPaolo Bonzini * - free->set, when setting the event 215fbcc3e50SPaolo Bonzini * - busy->set, when setting the event, followed by SetEvent 2167c9b2bf6SPaolo Bonzini * - set->free, when resetting the event 2177c9b2bf6SPaolo Bonzini * - free->busy, when waiting 2187c9b2bf6SPaolo Bonzini * 2197c9b2bf6SPaolo Bonzini * set->busy does not happen (it can be observed from the outside but 2207c9b2bf6SPaolo Bonzini * it really is set->free->busy). 2217c9b2bf6SPaolo Bonzini * 2227c9b2bf6SPaolo Bonzini * busy->free provably cannot happen; to enforce it, the set->free transition 2237c9b2bf6SPaolo Bonzini * is done with an OR, which becomes a no-op if the event has concurrently 2247c9b2bf6SPaolo Bonzini * transitioned to free or busy (and is faster than cmpxchg). 2257c9b2bf6SPaolo Bonzini */ 2267c9b2bf6SPaolo Bonzini 2277c9b2bf6SPaolo Bonzini #define EV_SET 0 2287c9b2bf6SPaolo Bonzini #define EV_FREE 1 2297c9b2bf6SPaolo Bonzini #define EV_BUSY -1 2307c9b2bf6SPaolo Bonzini 231c7c4d063SPaolo Bonzini void qemu_event_init(QemuEvent *ev, bool init) 232c7c4d063SPaolo Bonzini { 233c7c4d063SPaolo Bonzini /* Manual reset. */ 2347c9b2bf6SPaolo Bonzini ev->event = CreateEvent(NULL, TRUE, TRUE, NULL); 2357c9b2bf6SPaolo Bonzini ev->value = (init ? EV_SET : EV_FREE); 236c096358eSFam Zheng ev->initialized = true; 237c7c4d063SPaolo Bonzini } 238c7c4d063SPaolo Bonzini 239c7c4d063SPaolo Bonzini void qemu_event_destroy(QemuEvent *ev) 240c7c4d063SPaolo Bonzini { 241c096358eSFam Zheng assert(ev->initialized); 242c096358eSFam Zheng ev->initialized = false; 243c7c4d063SPaolo Bonzini CloseHandle(ev->event); 244c7c4d063SPaolo Bonzini } 245c7c4d063SPaolo Bonzini 246c7c4d063SPaolo Bonzini void qemu_event_set(QemuEvent *ev) 247c7c4d063SPaolo Bonzini { 248c096358eSFam Zheng assert(ev->initialized); 249374293caSPaolo Bonzini /* qemu_event_set has release semantics, but because it *loads* 250374293caSPaolo Bonzini * ev->value we need a full memory barrier here. 251374293caSPaolo Bonzini */ 252374293caSPaolo Bonzini smp_mb(); 253d73415a3SStefan Hajnoczi if (qatomic_read(&ev->value) != EV_SET) { 254d73415a3SStefan Hajnoczi if (qatomic_xchg(&ev->value, EV_SET) == EV_BUSY) { 2557c9b2bf6SPaolo Bonzini /* There were waiters, wake them up. */ 256c7c4d063SPaolo Bonzini SetEvent(ev->event); 257c7c4d063SPaolo Bonzini } 2587c9b2bf6SPaolo Bonzini } 2597c9b2bf6SPaolo Bonzini } 260c7c4d063SPaolo Bonzini 261c7c4d063SPaolo Bonzini void qemu_event_reset(QemuEvent *ev) 262c7c4d063SPaolo Bonzini { 263374293caSPaolo Bonzini unsigned value; 264374293caSPaolo Bonzini 265c096358eSFam Zheng assert(ev->initialized); 266d73415a3SStefan Hajnoczi value = qatomic_read(&ev->value); 267374293caSPaolo Bonzini smp_mb_acquire(); 268374293caSPaolo Bonzini if (value == EV_SET) { 2697c9b2bf6SPaolo Bonzini /* If there was a concurrent reset (or even reset+wait), 2707c9b2bf6SPaolo Bonzini * do nothing. Otherwise change EV_SET->EV_FREE. 2717c9b2bf6SPaolo Bonzini */ 272d73415a3SStefan Hajnoczi qatomic_or(&ev->value, EV_FREE); 2737c9b2bf6SPaolo Bonzini } 274c7c4d063SPaolo Bonzini } 275c7c4d063SPaolo Bonzini 276c7c4d063SPaolo Bonzini void qemu_event_wait(QemuEvent *ev) 277c7c4d063SPaolo Bonzini { 2787c9b2bf6SPaolo Bonzini unsigned value; 2797c9b2bf6SPaolo Bonzini 280c096358eSFam Zheng assert(ev->initialized); 281d73415a3SStefan Hajnoczi value = qatomic_read(&ev->value); 282374293caSPaolo Bonzini smp_mb_acquire(); 2837c9b2bf6SPaolo Bonzini if (value != EV_SET) { 2847c9b2bf6SPaolo Bonzini if (value == EV_FREE) { 2857c9b2bf6SPaolo Bonzini /* qemu_event_set is not yet going to call SetEvent, but we are 2867c9b2bf6SPaolo Bonzini * going to do another check for EV_SET below when setting EV_BUSY. 2877c9b2bf6SPaolo Bonzini * At that point it is safe to call WaitForSingleObject. 2887c9b2bf6SPaolo Bonzini */ 2897c9b2bf6SPaolo Bonzini ResetEvent(ev->event); 2907c9b2bf6SPaolo Bonzini 2917c9b2bf6SPaolo Bonzini /* Tell qemu_event_set that there are waiters. No need to retry 2928cc360b9Szhaolichang * because there cannot be a concurrent busy->free transition. 2937c9b2bf6SPaolo Bonzini * After the CAS, the event will be either set or busy. 2947c9b2bf6SPaolo Bonzini */ 295d73415a3SStefan Hajnoczi if (qatomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { 2967c9b2bf6SPaolo Bonzini value = EV_SET; 2977c9b2bf6SPaolo Bonzini } else { 2987c9b2bf6SPaolo Bonzini value = EV_BUSY; 2997c9b2bf6SPaolo Bonzini } 3007c9b2bf6SPaolo Bonzini } 3017c9b2bf6SPaolo Bonzini if (value == EV_BUSY) { 302c7c4d063SPaolo Bonzini WaitForSingleObject(ev->event, INFINITE); 303c7c4d063SPaolo Bonzini } 3047c9b2bf6SPaolo Bonzini } 3057c9b2bf6SPaolo Bonzini } 306c7c4d063SPaolo Bonzini 307baacf047SPaolo Bonzini struct QemuThreadData { 308baacf047SPaolo Bonzini /* Passed to win32_start_routine. */ 309baacf047SPaolo Bonzini void *(*start_routine)(void *); 310baacf047SPaolo Bonzini void *arg; 311baacf047SPaolo Bonzini short mode; 312ef57137fSPaolo Bonzini NotifierList exit; 313baacf047SPaolo Bonzini 314baacf047SPaolo Bonzini /* Only used for joinable threads. */ 315baacf047SPaolo Bonzini bool exited; 316baacf047SPaolo Bonzini void *ret; 317baacf047SPaolo Bonzini CRITICAL_SECTION cs; 318baacf047SPaolo Bonzini }; 319baacf047SPaolo Bonzini 320ef57137fSPaolo Bonzini static bool atexit_registered; 321ef57137fSPaolo Bonzini static NotifierList main_thread_exit; 322ef57137fSPaolo Bonzini 323baacf047SPaolo Bonzini static __thread QemuThreadData *qemu_thread_data; 324baacf047SPaolo Bonzini 325ef57137fSPaolo Bonzini static void run_main_thread_exit(void) 326ef57137fSPaolo Bonzini { 327ef57137fSPaolo Bonzini notifier_list_notify(&main_thread_exit, NULL); 328ef57137fSPaolo Bonzini } 329ef57137fSPaolo Bonzini 330ef57137fSPaolo Bonzini void qemu_thread_atexit_add(Notifier *notifier) 331ef57137fSPaolo Bonzini { 332ef57137fSPaolo Bonzini if (!qemu_thread_data) { 333ef57137fSPaolo Bonzini if (!atexit_registered) { 334ef57137fSPaolo Bonzini atexit_registered = true; 335ef57137fSPaolo Bonzini atexit(run_main_thread_exit); 336ef57137fSPaolo Bonzini } 337ef57137fSPaolo Bonzini notifier_list_add(&main_thread_exit, notifier); 338ef57137fSPaolo Bonzini } else { 339ef57137fSPaolo Bonzini notifier_list_add(&qemu_thread_data->exit, notifier); 340ef57137fSPaolo Bonzini } 341ef57137fSPaolo Bonzini } 342ef57137fSPaolo Bonzini 343ef57137fSPaolo Bonzini void qemu_thread_atexit_remove(Notifier *notifier) 344ef57137fSPaolo Bonzini { 345ef57137fSPaolo Bonzini notifier_remove(notifier); 346ef57137fSPaolo Bonzini } 347ef57137fSPaolo Bonzini 348baacf047SPaolo Bonzini static unsigned __stdcall win32_start_routine(void *arg) 349baacf047SPaolo Bonzini { 350baacf047SPaolo Bonzini QemuThreadData *data = (QemuThreadData *) arg; 351baacf047SPaolo Bonzini void *(*start_routine)(void *) = data->start_routine; 352baacf047SPaolo Bonzini void *thread_arg = data->arg; 353baacf047SPaolo Bonzini 354baacf047SPaolo Bonzini qemu_thread_data = data; 355baacf047SPaolo Bonzini qemu_thread_exit(start_routine(thread_arg)); 356baacf047SPaolo Bonzini abort(); 357baacf047SPaolo Bonzini } 358baacf047SPaolo Bonzini 359baacf047SPaolo Bonzini void qemu_thread_exit(void *arg) 360baacf047SPaolo Bonzini { 361baacf047SPaolo Bonzini QemuThreadData *data = qemu_thread_data; 362baacf047SPaolo Bonzini 363ef57137fSPaolo Bonzini notifier_list_notify(&data->exit, NULL); 364ef57137fSPaolo Bonzini if (data->mode == QEMU_THREAD_JOINABLE) { 365baacf047SPaolo Bonzini data->ret = arg; 366baacf047SPaolo Bonzini EnterCriticalSection(&data->cs); 367baacf047SPaolo Bonzini data->exited = true; 368baacf047SPaolo Bonzini LeaveCriticalSection(&data->cs); 369ef57137fSPaolo Bonzini } else { 370ef57137fSPaolo Bonzini g_free(data); 371baacf047SPaolo Bonzini } 372baacf047SPaolo Bonzini _endthreadex(0); 373baacf047SPaolo Bonzini } 374baacf047SPaolo Bonzini 375baacf047SPaolo Bonzini void *qemu_thread_join(QemuThread *thread) 376baacf047SPaolo Bonzini { 377baacf047SPaolo Bonzini QemuThreadData *data; 378baacf047SPaolo Bonzini void *ret; 379baacf047SPaolo Bonzini HANDLE handle; 380baacf047SPaolo Bonzini 381baacf047SPaolo Bonzini data = thread->data; 382ef57137fSPaolo Bonzini if (data->mode == QEMU_THREAD_DETACHED) { 383baacf047SPaolo Bonzini return NULL; 384baacf047SPaolo Bonzini } 385ef57137fSPaolo Bonzini 386baacf047SPaolo Bonzini /* 387baacf047SPaolo Bonzini * Because multiple copies of the QemuThread can exist via 388baacf047SPaolo Bonzini * qemu_thread_get_self, we need to store a value that cannot 389baacf047SPaolo Bonzini * leak there. The simplest, non racy way is to store the TID, 390baacf047SPaolo Bonzini * discard the handle that _beginthreadex gives back, and 391baacf047SPaolo Bonzini * get another copy of the handle here. 392baacf047SPaolo Bonzini */ 393baacf047SPaolo Bonzini handle = qemu_thread_get_handle(thread); 394baacf047SPaolo Bonzini if (handle) { 395baacf047SPaolo Bonzini WaitForSingleObject(handle, INFINITE); 396baacf047SPaolo Bonzini CloseHandle(handle); 397baacf047SPaolo Bonzini } 398baacf047SPaolo Bonzini ret = data->ret; 399baacf047SPaolo Bonzini DeleteCriticalSection(&data->cs); 400baacf047SPaolo Bonzini g_free(data); 401baacf047SPaolo Bonzini return ret; 402baacf047SPaolo Bonzini } 403baacf047SPaolo Bonzini 4044900116eSDr. David Alan Gilbert void qemu_thread_create(QemuThread *thread, const char *name, 405baacf047SPaolo Bonzini void *(*start_routine)(void *), 406baacf047SPaolo Bonzini void *arg, int mode) 407baacf047SPaolo Bonzini { 408baacf047SPaolo Bonzini HANDLE hThread; 409baacf047SPaolo Bonzini struct QemuThreadData *data; 410baacf047SPaolo Bonzini 411baacf047SPaolo Bonzini data = g_malloc(sizeof *data); 412baacf047SPaolo Bonzini data->start_routine = start_routine; 413baacf047SPaolo Bonzini data->arg = arg; 414baacf047SPaolo Bonzini data->mode = mode; 415baacf047SPaolo Bonzini data->exited = false; 416ef57137fSPaolo Bonzini notifier_list_init(&data->exit); 417baacf047SPaolo Bonzini 418baacf047SPaolo Bonzini if (data->mode != QEMU_THREAD_DETACHED) { 419baacf047SPaolo Bonzini InitializeCriticalSection(&data->cs); 420baacf047SPaolo Bonzini } 421baacf047SPaolo Bonzini 422baacf047SPaolo Bonzini hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine, 423baacf047SPaolo Bonzini data, 0, &thread->tid); 424baacf047SPaolo Bonzini if (!hThread) { 425baacf047SPaolo Bonzini error_exit(GetLastError(), __func__); 426baacf047SPaolo Bonzini } 427baacf047SPaolo Bonzini CloseHandle(hThread); 428ef57137fSPaolo Bonzini thread->data = data; 429baacf047SPaolo Bonzini } 430baacf047SPaolo Bonzini 431baacf047SPaolo Bonzini void qemu_thread_get_self(QemuThread *thread) 432baacf047SPaolo Bonzini { 433baacf047SPaolo Bonzini thread->data = qemu_thread_data; 434baacf047SPaolo Bonzini thread->tid = GetCurrentThreadId(); 435baacf047SPaolo Bonzini } 436baacf047SPaolo Bonzini 437baacf047SPaolo Bonzini HANDLE qemu_thread_get_handle(QemuThread *thread) 438baacf047SPaolo Bonzini { 439baacf047SPaolo Bonzini QemuThreadData *data; 440baacf047SPaolo Bonzini HANDLE handle; 441baacf047SPaolo Bonzini 442baacf047SPaolo Bonzini data = thread->data; 443ef57137fSPaolo Bonzini if (data->mode == QEMU_THREAD_DETACHED) { 444baacf047SPaolo Bonzini return NULL; 445baacf047SPaolo Bonzini } 446baacf047SPaolo Bonzini 447baacf047SPaolo Bonzini EnterCriticalSection(&data->cs); 448baacf047SPaolo Bonzini if (!data->exited) { 449b0cb0a66SVincent Palatin handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME | 450b0cb0a66SVincent Palatin THREAD_SET_CONTEXT, FALSE, thread->tid); 451baacf047SPaolo Bonzini } else { 452baacf047SPaolo Bonzini handle = NULL; 453baacf047SPaolo Bonzini } 454baacf047SPaolo Bonzini LeaveCriticalSection(&data->cs); 455baacf047SPaolo Bonzini return handle; 456baacf047SPaolo Bonzini } 457baacf047SPaolo Bonzini 458baacf047SPaolo Bonzini bool qemu_thread_is_self(QemuThread *thread) 459baacf047SPaolo Bonzini { 460baacf047SPaolo Bonzini return GetCurrentThreadId() == thread->tid; 461baacf047SPaolo Bonzini } 462