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/thread.h" 16 #include "qemu/notify.h" 17 #include "qemu-thread-common.h" 18 #include <process.h> 19 20 static bool name_threads; 21 22 typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread, 23 PCWSTR lpThreadDescription); 24 static pSetThreadDescription SetThreadDescriptionFunc; 25 static HMODULE kernel32_module; 26 27 static bool load_set_thread_description(void) 28 { 29 static gsize _init_once = 0; 30 31 if (g_once_init_enter(&_init_once)) { 32 kernel32_module = LoadLibrary("kernel32.dll"); 33 if (kernel32_module) { 34 SetThreadDescriptionFunc = 35 (pSetThreadDescription)GetProcAddress(kernel32_module, 36 "SetThreadDescription"); 37 if (!SetThreadDescriptionFunc) { 38 FreeLibrary(kernel32_module); 39 } 40 } 41 g_once_init_leave(&_init_once, 1); 42 } 43 44 return !!SetThreadDescriptionFunc; 45 } 46 47 void qemu_thread_naming(bool enable) 48 { 49 name_threads = enable; 50 51 if (enable && !load_set_thread_description()) { 52 fprintf(stderr, "qemu: thread naming not supported on this host\n"); 53 name_threads = false; 54 } 55 } 56 57 static void error_exit(int err, const char *msg) 58 { 59 char *pstr; 60 61 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 62 NULL, err, 0, (LPTSTR)&pstr, 2, NULL); 63 fprintf(stderr, "qemu: %s: %s\n", msg, pstr); 64 LocalFree(pstr); 65 abort(); 66 } 67 68 void qemu_mutex_init(QemuMutex *mutex) 69 { 70 InitializeSRWLock(&mutex->lock); 71 qemu_mutex_post_init(mutex); 72 } 73 74 void qemu_mutex_destroy(QemuMutex *mutex) 75 { 76 assert(mutex->initialized); 77 mutex->initialized = false; 78 InitializeSRWLock(&mutex->lock); 79 } 80 81 void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line) 82 { 83 assert(mutex->initialized); 84 qemu_mutex_pre_lock(mutex, file, line); 85 AcquireSRWLockExclusive(&mutex->lock); 86 qemu_mutex_post_lock(mutex, file, line); 87 } 88 89 int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line) 90 { 91 int owned; 92 93 assert(mutex->initialized); 94 owned = TryAcquireSRWLockExclusive(&mutex->lock); 95 if (owned) { 96 qemu_mutex_post_lock(mutex, file, line); 97 return 0; 98 } 99 return -EBUSY; 100 } 101 102 void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line) 103 { 104 assert(mutex->initialized); 105 qemu_mutex_pre_unlock(mutex, file, line); 106 ReleaseSRWLockExclusive(&mutex->lock); 107 } 108 109 void qemu_rec_mutex_init(QemuRecMutex *mutex) 110 { 111 InitializeCriticalSection(&mutex->lock); 112 mutex->initialized = true; 113 } 114 115 void qemu_rec_mutex_destroy(QemuRecMutex *mutex) 116 { 117 assert(mutex->initialized); 118 mutex->initialized = false; 119 DeleteCriticalSection(&mutex->lock); 120 } 121 122 void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line) 123 { 124 assert(mutex->initialized); 125 EnterCriticalSection(&mutex->lock); 126 } 127 128 int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file, int line) 129 { 130 assert(mutex->initialized); 131 return !TryEnterCriticalSection(&mutex->lock); 132 } 133 134 void qemu_rec_mutex_unlock_impl(QemuRecMutex *mutex, const char *file, int line) 135 { 136 assert(mutex->initialized); 137 LeaveCriticalSection(&mutex->lock); 138 } 139 140 void qemu_cond_init(QemuCond *cond) 141 { 142 memset(cond, 0, sizeof(*cond)); 143 InitializeConditionVariable(&cond->var); 144 cond->initialized = true; 145 } 146 147 void qemu_cond_destroy(QemuCond *cond) 148 { 149 assert(cond->initialized); 150 cond->initialized = false; 151 InitializeConditionVariable(&cond->var); 152 } 153 154 void qemu_cond_signal(QemuCond *cond) 155 { 156 assert(cond->initialized); 157 WakeConditionVariable(&cond->var); 158 } 159 160 void qemu_cond_broadcast(QemuCond *cond) 161 { 162 assert(cond->initialized); 163 WakeAllConditionVariable(&cond->var); 164 } 165 166 void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line) 167 { 168 assert(cond->initialized); 169 qemu_mutex_pre_unlock(mutex, file, line); 170 SleepConditionVariableSRW(&cond->var, &mutex->lock, INFINITE, 0); 171 qemu_mutex_post_lock(mutex, file, line); 172 } 173 174 bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, 175 const char *file, const int line) 176 { 177 int rc = 0; 178 179 assert(cond->initialized); 180 trace_qemu_mutex_unlock(mutex, file, line); 181 if (!SleepConditionVariableSRW(&cond->var, &mutex->lock, ms, 0)) { 182 rc = GetLastError(); 183 } 184 trace_qemu_mutex_locked(mutex, file, line); 185 if (rc && rc != ERROR_TIMEOUT) { 186 error_exit(rc, __func__); 187 } 188 return rc != ERROR_TIMEOUT; 189 } 190 191 void qemu_sem_init(QemuSemaphore *sem, int init) 192 { 193 /* Manual reset. */ 194 sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL); 195 sem->initialized = true; 196 } 197 198 void qemu_sem_destroy(QemuSemaphore *sem) 199 { 200 assert(sem->initialized); 201 sem->initialized = false; 202 CloseHandle(sem->sema); 203 } 204 205 void qemu_sem_post(QemuSemaphore *sem) 206 { 207 assert(sem->initialized); 208 ReleaseSemaphore(sem->sema, 1, NULL); 209 } 210 211 int qemu_sem_timedwait(QemuSemaphore *sem, int ms) 212 { 213 int rc; 214 215 assert(sem->initialized); 216 rc = WaitForSingleObject(sem->sema, ms); 217 if (rc == WAIT_OBJECT_0) { 218 return 0; 219 } 220 if (rc != WAIT_TIMEOUT) { 221 error_exit(GetLastError(), __func__); 222 } 223 return -1; 224 } 225 226 void qemu_sem_wait(QemuSemaphore *sem) 227 { 228 assert(sem->initialized); 229 if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) { 230 error_exit(GetLastError(), __func__); 231 } 232 } 233 234 /* Wrap a Win32 manual-reset event with a fast userspace path. The idea 235 * is to reset the Win32 event lazily, as part of a test-reset-test-wait 236 * sequence. Such a sequence is, indeed, how QemuEvents are used by 237 * RCU and other subsystems! 238 * 239 * Valid transitions: 240 * - free->set, when setting the event 241 * - busy->set, when setting the event, followed by SetEvent 242 * - set->free, when resetting the event 243 * - free->busy, when waiting 244 * 245 * set->busy does not happen (it can be observed from the outside but 246 * it really is set->free->busy). 247 * 248 * busy->free provably cannot happen; to enforce it, the set->free transition 249 * is done with an OR, which becomes a no-op if the event has concurrently 250 * transitioned to free or busy (and is faster than cmpxchg). 251 */ 252 253 #define EV_SET 0 254 #define EV_FREE 1 255 #define EV_BUSY -1 256 257 void qemu_event_init(QemuEvent *ev, bool init) 258 { 259 /* Manual reset. */ 260 ev->event = CreateEvent(NULL, TRUE, TRUE, NULL); 261 ev->value = (init ? EV_SET : EV_FREE); 262 ev->initialized = true; 263 } 264 265 void qemu_event_destroy(QemuEvent *ev) 266 { 267 assert(ev->initialized); 268 ev->initialized = false; 269 CloseHandle(ev->event); 270 } 271 272 void qemu_event_set(QemuEvent *ev) 273 { 274 assert(ev->initialized); 275 276 /* 277 * Pairs with both qemu_event_reset() and qemu_event_wait(). 278 * 279 * qemu_event_set has release semantics, but because it *loads* 280 * ev->value we need a full memory barrier here. 281 */ 282 smp_mb(); 283 if (qatomic_read(&ev->value) != EV_SET) { 284 int old = qatomic_xchg(&ev->value, EV_SET); 285 286 /* Pairs with memory barrier after ResetEvent. */ 287 smp_mb__after_rmw(); 288 if (old == EV_BUSY) { 289 /* There were waiters, wake them up. */ 290 SetEvent(ev->event); 291 } 292 } 293 } 294 295 void qemu_event_reset(QemuEvent *ev) 296 { 297 assert(ev->initialized); 298 299 /* 300 * If there was a concurrent reset (or even reset+wait), 301 * do nothing. Otherwise change EV_SET->EV_FREE. 302 */ 303 qatomic_or(&ev->value, EV_FREE); 304 305 /* 306 * Order reset before checking the condition in the caller. 307 * Pairs with the first memory barrier in qemu_event_set(). 308 */ 309 smp_mb__after_rmw(); 310 } 311 312 void qemu_event_wait(QemuEvent *ev) 313 { 314 unsigned value; 315 316 assert(ev->initialized); 317 318 /* 319 * qemu_event_wait must synchronize with qemu_event_set even if it does 320 * not go down the slow path, so this load-acquire is needed that 321 * synchronizes with the first memory barrier in qemu_event_set(). 322 * 323 * If we do go down the slow path, there is no requirement at all: we 324 * might miss a qemu_event_set() here but ultimately the memory barrier in 325 * qemu_futex_wait() will ensure the check is done correctly. 326 */ 327 value = qatomic_load_acquire(&ev->value); 328 if (value != EV_SET) { 329 if (value == EV_FREE) { 330 /* 331 * Here the underlying kernel event is reset, but qemu_event_set is 332 * not yet going to call SetEvent. However, there will be another 333 * check for EV_SET below when setting EV_BUSY. At that point it 334 * is safe to call WaitForSingleObject. 335 */ 336 ResetEvent(ev->event); 337 338 /* 339 * It is not clear whether ResetEvent provides this barrier; kernel 340 * APIs (KeResetEvent/KeClearEvent) do not. Better safe than sorry! 341 */ 342 smp_mb(); 343 344 /* 345 * Leave the event reset and tell qemu_event_set that there are 346 * waiters. No need to retry, because there cannot be a concurrent 347 * busy->free transition. After the CAS, the event will be either 348 * set or busy. 349 */ 350 if (qatomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { 351 return; 352 } 353 } 354 355 /* 356 * ev->value is now EV_BUSY. Since we didn't observe EV_SET, 357 * qemu_event_set() must observe EV_BUSY and call SetEvent(). 358 */ 359 WaitForSingleObject(ev->event, INFINITE); 360 } 361 } 362 363 struct QemuThreadData { 364 /* Passed to win32_start_routine. */ 365 void *(*start_routine)(void *); 366 void *arg; 367 short mode; 368 NotifierList exit; 369 370 /* Only used for joinable threads. */ 371 bool exited; 372 void *ret; 373 CRITICAL_SECTION cs; 374 }; 375 376 static bool atexit_registered; 377 static NotifierList main_thread_exit; 378 379 static __thread QemuThreadData *qemu_thread_data; 380 381 static void run_main_thread_exit(void) 382 { 383 notifier_list_notify(&main_thread_exit, NULL); 384 } 385 386 void qemu_thread_atexit_add(Notifier *notifier) 387 { 388 if (!qemu_thread_data) { 389 if (!atexit_registered) { 390 atexit_registered = true; 391 atexit(run_main_thread_exit); 392 } 393 notifier_list_add(&main_thread_exit, notifier); 394 } else { 395 notifier_list_add(&qemu_thread_data->exit, notifier); 396 } 397 } 398 399 void qemu_thread_atexit_remove(Notifier *notifier) 400 { 401 notifier_remove(notifier); 402 } 403 404 static unsigned __stdcall win32_start_routine(void *arg) 405 { 406 QemuThreadData *data = (QemuThreadData *) arg; 407 void *(*start_routine)(void *) = data->start_routine; 408 void *thread_arg = data->arg; 409 410 qemu_thread_data = data; 411 qemu_thread_exit(start_routine(thread_arg)); 412 abort(); 413 } 414 415 void qemu_thread_exit(void *arg) 416 { 417 QemuThreadData *data = qemu_thread_data; 418 419 notifier_list_notify(&data->exit, NULL); 420 if (data->mode == QEMU_THREAD_JOINABLE) { 421 data->ret = arg; 422 EnterCriticalSection(&data->cs); 423 data->exited = true; 424 LeaveCriticalSection(&data->cs); 425 } else { 426 g_free(data); 427 } 428 _endthreadex(0); 429 } 430 431 void *qemu_thread_join(QemuThread *thread) 432 { 433 QemuThreadData *data; 434 void *ret; 435 HANDLE handle; 436 437 data = thread->data; 438 if (data->mode == QEMU_THREAD_DETACHED) { 439 return NULL; 440 } 441 442 /* 443 * Because multiple copies of the QemuThread can exist via 444 * qemu_thread_get_self, we need to store a value that cannot 445 * leak there. The simplest, non racy way is to store the TID, 446 * discard the handle that _beginthreadex gives back, and 447 * get another copy of the handle here. 448 */ 449 handle = qemu_thread_get_handle(thread); 450 if (handle) { 451 WaitForSingleObject(handle, INFINITE); 452 CloseHandle(handle); 453 } 454 ret = data->ret; 455 DeleteCriticalSection(&data->cs); 456 g_free(data); 457 return ret; 458 } 459 460 static bool set_thread_description(HANDLE h, const char *name) 461 { 462 HRESULT hr; 463 g_autofree wchar_t *namew = NULL; 464 465 if (!load_set_thread_description()) { 466 return false; 467 } 468 469 namew = g_utf8_to_utf16(name, -1, NULL, NULL, NULL); 470 if (!namew) { 471 return false; 472 } 473 474 hr = SetThreadDescriptionFunc(h, namew); 475 476 return SUCCEEDED(hr); 477 } 478 479 void qemu_thread_create(QemuThread *thread, const char *name, 480 void *(*start_routine)(void *), 481 void *arg, int mode) 482 { 483 HANDLE hThread; 484 struct QemuThreadData *data; 485 486 data = g_malloc(sizeof *data); 487 data->start_routine = start_routine; 488 data->arg = arg; 489 data->mode = mode; 490 data->exited = false; 491 notifier_list_init(&data->exit); 492 493 if (data->mode != QEMU_THREAD_DETACHED) { 494 InitializeCriticalSection(&data->cs); 495 } 496 497 hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine, 498 data, 0, &thread->tid); 499 if (!hThread) { 500 error_exit(GetLastError(), __func__); 501 } 502 if (name_threads && name && !set_thread_description(hThread, name)) { 503 fprintf(stderr, "qemu: failed to set thread description: %s\n", name); 504 } 505 CloseHandle(hThread); 506 507 thread->data = data; 508 } 509 510 int qemu_thread_set_affinity(QemuThread *thread, unsigned long *host_cpus, 511 unsigned long nbits) 512 { 513 return -ENOSYS; 514 } 515 516 int qemu_thread_get_affinity(QemuThread *thread, unsigned long **host_cpus, 517 unsigned long *nbits) 518 { 519 return -ENOSYS; 520 } 521 522 void qemu_thread_get_self(QemuThread *thread) 523 { 524 thread->data = qemu_thread_data; 525 thread->tid = GetCurrentThreadId(); 526 } 527 528 HANDLE qemu_thread_get_handle(QemuThread *thread) 529 { 530 QemuThreadData *data; 531 HANDLE handle; 532 533 data = thread->data; 534 if (data->mode == QEMU_THREAD_DETACHED) { 535 return NULL; 536 } 537 538 EnterCriticalSection(&data->cs); 539 if (!data->exited) { 540 handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME | 541 THREAD_SET_CONTEXT, FALSE, thread->tid); 542 } else { 543 handle = NULL; 544 } 545 LeaveCriticalSection(&data->cs); 546 return handle; 547 } 548 549 bool qemu_thread_is_self(QemuThread *thread) 550 { 551 return GetCurrentThreadId() == thread->tid; 552 } 553