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 14 #include "qemu/osdep.h" 15 #include "qemu-common.h" 16 #include "qemu/thread.h" 17 #include "qemu/notify.h" 18 #include "qemu-thread-common.h" 19 #include <process.h> 20 21 static bool name_threads; 22 23 void qemu_thread_naming(bool enable) 24 { 25 /* But note we don't actually name them on Windows yet */ 26 name_threads = enable; 27 28 fprintf(stderr, "qemu: thread naming not supported on this host\n"); 29 } 30 31 static void error_exit(int err, const char *msg) 32 { 33 char *pstr; 34 35 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 36 NULL, err, 0, (LPTSTR)&pstr, 2, NULL); 37 fprintf(stderr, "qemu: %s: %s\n", msg, pstr); 38 LocalFree(pstr); 39 abort(); 40 } 41 42 void qemu_mutex_init(QemuMutex *mutex) 43 { 44 InitializeSRWLock(&mutex->lock); 45 qemu_mutex_post_init(mutex); 46 } 47 48 void qemu_mutex_destroy(QemuMutex *mutex) 49 { 50 assert(mutex->initialized); 51 mutex->initialized = false; 52 InitializeSRWLock(&mutex->lock); 53 } 54 55 void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line) 56 { 57 assert(mutex->initialized); 58 qemu_mutex_pre_lock(mutex, file, line); 59 AcquireSRWLockExclusive(&mutex->lock); 60 qemu_mutex_post_lock(mutex, file, line); 61 } 62 63 int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line) 64 { 65 int owned; 66 67 assert(mutex->initialized); 68 owned = TryAcquireSRWLockExclusive(&mutex->lock); 69 if (owned) { 70 qemu_mutex_post_lock(mutex, file, line); 71 return 0; 72 } 73 return -EBUSY; 74 } 75 76 void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line) 77 { 78 assert(mutex->initialized); 79 qemu_mutex_pre_unlock(mutex, file, line); 80 ReleaseSRWLockExclusive(&mutex->lock); 81 } 82 83 void qemu_rec_mutex_init(QemuRecMutex *mutex) 84 { 85 InitializeCriticalSection(&mutex->lock); 86 mutex->initialized = true; 87 } 88 89 void qemu_rec_mutex_destroy(QemuRecMutex *mutex) 90 { 91 assert(mutex->initialized); 92 mutex->initialized = false; 93 DeleteCriticalSection(&mutex->lock); 94 } 95 96 void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line) 97 { 98 assert(mutex->initialized); 99 EnterCriticalSection(&mutex->lock); 100 } 101 102 int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file, int line) 103 { 104 assert(mutex->initialized); 105 return !TryEnterCriticalSection(&mutex->lock); 106 } 107 108 void qemu_rec_mutex_unlock(QemuRecMutex *mutex) 109 { 110 assert(mutex->initialized); 111 LeaveCriticalSection(&mutex->lock); 112 } 113 114 void qemu_cond_init(QemuCond *cond) 115 { 116 memset(cond, 0, sizeof(*cond)); 117 InitializeConditionVariable(&cond->var); 118 cond->initialized = true; 119 } 120 121 void qemu_cond_destroy(QemuCond *cond) 122 { 123 assert(cond->initialized); 124 cond->initialized = false; 125 InitializeConditionVariable(&cond->var); 126 } 127 128 void qemu_cond_signal(QemuCond *cond) 129 { 130 assert(cond->initialized); 131 WakeConditionVariable(&cond->var); 132 } 133 134 void qemu_cond_broadcast(QemuCond *cond) 135 { 136 assert(cond->initialized); 137 WakeAllConditionVariable(&cond->var); 138 } 139 140 void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line) 141 { 142 assert(cond->initialized); 143 qemu_mutex_pre_unlock(mutex, file, line); 144 SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0); 145 qemu_mutex_post_lock(mutex, file, line); 146 } 147 148 void qemu_sem_init(QemuSemaphore *sem, int init) 149 { 150 /* Manual reset. */ 151 sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL); 152 sem->initialized = true; 153 } 154 155 void qemu_sem_destroy(QemuSemaphore *sem) 156 { 157 assert(sem->initialized); 158 sem->initialized = false; 159 CloseHandle(sem->sema); 160 } 161 162 void qemu_sem_post(QemuSemaphore *sem) 163 { 164 assert(sem->initialized); 165 ReleaseSemaphore(sem->sema, 1, NULL); 166 } 167 168 int qemu_sem_timedwait(QemuSemaphore *sem, int ms) 169 { 170 int rc; 171 172 assert(sem->initialized); 173 rc = WaitForSingleObject(sem->sema, ms); 174 if (rc == WAIT_OBJECT_0) { 175 return 0; 176 } 177 if (rc != WAIT_TIMEOUT) { 178 error_exit(GetLastError(), __func__); 179 } 180 return -1; 181 } 182 183 void qemu_sem_wait(QemuSemaphore *sem) 184 { 185 assert(sem->initialized); 186 if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) { 187 error_exit(GetLastError(), __func__); 188 } 189 } 190 191 /* Wrap a Win32 manual-reset event with a fast userspace path. The idea 192 * is to reset the Win32 event lazily, as part of a test-reset-test-wait 193 * sequence. Such a sequence is, indeed, how QemuEvents are used by 194 * RCU and other subsystems! 195 * 196 * Valid transitions: 197 * - free->set, when setting the event 198 * - busy->set, when setting the event, followed by SetEvent 199 * - set->free, when resetting the event 200 * - free->busy, when waiting 201 * 202 * set->busy does not happen (it can be observed from the outside but 203 * it really is set->free->busy). 204 * 205 * busy->free provably cannot happen; to enforce it, the set->free transition 206 * is done with an OR, which becomes a no-op if the event has concurrently 207 * transitioned to free or busy (and is faster than cmpxchg). 208 */ 209 210 #define EV_SET 0 211 #define EV_FREE 1 212 #define EV_BUSY -1 213 214 void qemu_event_init(QemuEvent *ev, bool init) 215 { 216 /* Manual reset. */ 217 ev->event = CreateEvent(NULL, TRUE, TRUE, NULL); 218 ev->value = (init ? EV_SET : EV_FREE); 219 ev->initialized = true; 220 } 221 222 void qemu_event_destroy(QemuEvent *ev) 223 { 224 assert(ev->initialized); 225 ev->initialized = false; 226 CloseHandle(ev->event); 227 } 228 229 void qemu_event_set(QemuEvent *ev) 230 { 231 assert(ev->initialized); 232 /* qemu_event_set has release semantics, but because it *loads* 233 * ev->value we need a full memory barrier here. 234 */ 235 smp_mb(); 236 if (atomic_read(&ev->value) != EV_SET) { 237 if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) { 238 /* There were waiters, wake them up. */ 239 SetEvent(ev->event); 240 } 241 } 242 } 243 244 void qemu_event_reset(QemuEvent *ev) 245 { 246 unsigned value; 247 248 assert(ev->initialized); 249 value = atomic_read(&ev->value); 250 smp_mb_acquire(); 251 if (value == EV_SET) { 252 /* If there was a concurrent reset (or even reset+wait), 253 * do nothing. Otherwise change EV_SET->EV_FREE. 254 */ 255 atomic_or(&ev->value, EV_FREE); 256 } 257 } 258 259 void qemu_event_wait(QemuEvent *ev) 260 { 261 unsigned value; 262 263 assert(ev->initialized); 264 value = atomic_read(&ev->value); 265 smp_mb_acquire(); 266 if (value != EV_SET) { 267 if (value == EV_FREE) { 268 /* qemu_event_set is not yet going to call SetEvent, but we are 269 * going to do another check for EV_SET below when setting EV_BUSY. 270 * At that point it is safe to call WaitForSingleObject. 271 */ 272 ResetEvent(ev->event); 273 274 /* Tell qemu_event_set that there are waiters. No need to retry 275 * because there cannot be a concurent busy->free transition. 276 * After the CAS, the event will be either set or busy. 277 */ 278 if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { 279 value = EV_SET; 280 } else { 281 value = EV_BUSY; 282 } 283 } 284 if (value == EV_BUSY) { 285 WaitForSingleObject(ev->event, INFINITE); 286 } 287 } 288 } 289 290 struct QemuThreadData { 291 /* Passed to win32_start_routine. */ 292 void *(*start_routine)(void *); 293 void *arg; 294 short mode; 295 NotifierList exit; 296 297 /* Only used for joinable threads. */ 298 bool exited; 299 void *ret; 300 CRITICAL_SECTION cs; 301 }; 302 303 static bool atexit_registered; 304 static NotifierList main_thread_exit; 305 306 static __thread QemuThreadData *qemu_thread_data; 307 308 static void run_main_thread_exit(void) 309 { 310 notifier_list_notify(&main_thread_exit, NULL); 311 } 312 313 void qemu_thread_atexit_add(Notifier *notifier) 314 { 315 if (!qemu_thread_data) { 316 if (!atexit_registered) { 317 atexit_registered = true; 318 atexit(run_main_thread_exit); 319 } 320 notifier_list_add(&main_thread_exit, notifier); 321 } else { 322 notifier_list_add(&qemu_thread_data->exit, notifier); 323 } 324 } 325 326 void qemu_thread_atexit_remove(Notifier *notifier) 327 { 328 notifier_remove(notifier); 329 } 330 331 static unsigned __stdcall win32_start_routine(void *arg) 332 { 333 QemuThreadData *data = (QemuThreadData *) arg; 334 void *(*start_routine)(void *) = data->start_routine; 335 void *thread_arg = data->arg; 336 337 qemu_thread_data = data; 338 qemu_thread_exit(start_routine(thread_arg)); 339 abort(); 340 } 341 342 void qemu_thread_exit(void *arg) 343 { 344 QemuThreadData *data = qemu_thread_data; 345 346 notifier_list_notify(&data->exit, NULL); 347 if (data->mode == QEMU_THREAD_JOINABLE) { 348 data->ret = arg; 349 EnterCriticalSection(&data->cs); 350 data->exited = true; 351 LeaveCriticalSection(&data->cs); 352 } else { 353 g_free(data); 354 } 355 _endthreadex(0); 356 } 357 358 void *qemu_thread_join(QemuThread *thread) 359 { 360 QemuThreadData *data; 361 void *ret; 362 HANDLE handle; 363 364 data = thread->data; 365 if (data->mode == QEMU_THREAD_DETACHED) { 366 return NULL; 367 } 368 369 /* 370 * Because multiple copies of the QemuThread can exist via 371 * qemu_thread_get_self, we need to store a value that cannot 372 * leak there. The simplest, non racy way is to store the TID, 373 * discard the handle that _beginthreadex gives back, and 374 * get another copy of the handle here. 375 */ 376 handle = qemu_thread_get_handle(thread); 377 if (handle) { 378 WaitForSingleObject(handle, INFINITE); 379 CloseHandle(handle); 380 } 381 ret = data->ret; 382 DeleteCriticalSection(&data->cs); 383 g_free(data); 384 return ret; 385 } 386 387 void qemu_thread_create(QemuThread *thread, const char *name, 388 void *(*start_routine)(void *), 389 void *arg, int mode) 390 { 391 HANDLE hThread; 392 struct QemuThreadData *data; 393 394 data = g_malloc(sizeof *data); 395 data->start_routine = start_routine; 396 data->arg = arg; 397 data->mode = mode; 398 data->exited = false; 399 notifier_list_init(&data->exit); 400 401 if (data->mode != QEMU_THREAD_DETACHED) { 402 InitializeCriticalSection(&data->cs); 403 } 404 405 hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine, 406 data, 0, &thread->tid); 407 if (!hThread) { 408 error_exit(GetLastError(), __func__); 409 } 410 CloseHandle(hThread); 411 thread->data = data; 412 } 413 414 void qemu_thread_get_self(QemuThread *thread) 415 { 416 thread->data = qemu_thread_data; 417 thread->tid = GetCurrentThreadId(); 418 } 419 420 HANDLE qemu_thread_get_handle(QemuThread *thread) 421 { 422 QemuThreadData *data; 423 HANDLE handle; 424 425 data = thread->data; 426 if (data->mode == QEMU_THREAD_DETACHED) { 427 return NULL; 428 } 429 430 EnterCriticalSection(&data->cs); 431 if (!data->exited) { 432 handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME | 433 THREAD_SET_CONTEXT, FALSE, thread->tid); 434 } else { 435 handle = NULL; 436 } 437 LeaveCriticalSection(&data->cs); 438 return handle; 439 } 440 441 bool qemu_thread_is_self(QemuThread *thread) 442 { 443 return GetCurrentThreadId() == thread->tid; 444 } 445