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 bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, 149 const char *file, const int line) 150 { 151 int rc = 0; 152 153 assert(cond->initialized); 154 trace_qemu_mutex_unlock(mutex, file, line); 155 if (!SleepConditionVariableSRW(&cond->var, &mutex->lock, ms, 0)) { 156 rc = GetLastError(); 157 } 158 trace_qemu_mutex_locked(mutex, file, line); 159 if (rc && rc != ERROR_TIMEOUT) { 160 error_exit(rc, __func__); 161 } 162 return rc != ERROR_TIMEOUT; 163 } 164 165 void qemu_sem_init(QemuSemaphore *sem, int init) 166 { 167 /* Manual reset. */ 168 sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL); 169 sem->initialized = true; 170 } 171 172 void qemu_sem_destroy(QemuSemaphore *sem) 173 { 174 assert(sem->initialized); 175 sem->initialized = false; 176 CloseHandle(sem->sema); 177 } 178 179 void qemu_sem_post(QemuSemaphore *sem) 180 { 181 assert(sem->initialized); 182 ReleaseSemaphore(sem->sema, 1, NULL); 183 } 184 185 int qemu_sem_timedwait(QemuSemaphore *sem, int ms) 186 { 187 int rc; 188 189 assert(sem->initialized); 190 rc = WaitForSingleObject(sem->sema, ms); 191 if (rc == WAIT_OBJECT_0) { 192 return 0; 193 } 194 if (rc != WAIT_TIMEOUT) { 195 error_exit(GetLastError(), __func__); 196 } 197 return -1; 198 } 199 200 void qemu_sem_wait(QemuSemaphore *sem) 201 { 202 assert(sem->initialized); 203 if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) { 204 error_exit(GetLastError(), __func__); 205 } 206 } 207 208 /* Wrap a Win32 manual-reset event with a fast userspace path. The idea 209 * is to reset the Win32 event lazily, as part of a test-reset-test-wait 210 * sequence. Such a sequence is, indeed, how QemuEvents are used by 211 * RCU and other subsystems! 212 * 213 * Valid transitions: 214 * - free->set, when setting the event 215 * - busy->set, when setting the event, followed by SetEvent 216 * - set->free, when resetting the event 217 * - free->busy, when waiting 218 * 219 * set->busy does not happen (it can be observed from the outside but 220 * it really is set->free->busy). 221 * 222 * busy->free provably cannot happen; to enforce it, the set->free transition 223 * is done with an OR, which becomes a no-op if the event has concurrently 224 * transitioned to free or busy (and is faster than cmpxchg). 225 */ 226 227 #define EV_SET 0 228 #define EV_FREE 1 229 #define EV_BUSY -1 230 231 void qemu_event_init(QemuEvent *ev, bool init) 232 { 233 /* Manual reset. */ 234 ev->event = CreateEvent(NULL, TRUE, TRUE, NULL); 235 ev->value = (init ? EV_SET : EV_FREE); 236 ev->initialized = true; 237 } 238 239 void qemu_event_destroy(QemuEvent *ev) 240 { 241 assert(ev->initialized); 242 ev->initialized = false; 243 CloseHandle(ev->event); 244 } 245 246 void qemu_event_set(QemuEvent *ev) 247 { 248 assert(ev->initialized); 249 /* qemu_event_set has release semantics, but because it *loads* 250 * ev->value we need a full memory barrier here. 251 */ 252 smp_mb(); 253 if (atomic_read(&ev->value) != EV_SET) { 254 if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) { 255 /* There were waiters, wake them up. */ 256 SetEvent(ev->event); 257 } 258 } 259 } 260 261 void qemu_event_reset(QemuEvent *ev) 262 { 263 unsigned value; 264 265 assert(ev->initialized); 266 value = atomic_read(&ev->value); 267 smp_mb_acquire(); 268 if (value == EV_SET) { 269 /* If there was a concurrent reset (or even reset+wait), 270 * do nothing. Otherwise change EV_SET->EV_FREE. 271 */ 272 atomic_or(&ev->value, EV_FREE); 273 } 274 } 275 276 void qemu_event_wait(QemuEvent *ev) 277 { 278 unsigned value; 279 280 assert(ev->initialized); 281 value = atomic_read(&ev->value); 282 smp_mb_acquire(); 283 if (value != EV_SET) { 284 if (value == EV_FREE) { 285 /* qemu_event_set is not yet going to call SetEvent, but we are 286 * going to do another check for EV_SET below when setting EV_BUSY. 287 * At that point it is safe to call WaitForSingleObject. 288 */ 289 ResetEvent(ev->event); 290 291 /* Tell qemu_event_set that there are waiters. No need to retry 292 * because there cannot be a concurent busy->free transition. 293 * After the CAS, the event will be either set or busy. 294 */ 295 if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { 296 value = EV_SET; 297 } else { 298 value = EV_BUSY; 299 } 300 } 301 if (value == EV_BUSY) { 302 WaitForSingleObject(ev->event, INFINITE); 303 } 304 } 305 } 306 307 struct QemuThreadData { 308 /* Passed to win32_start_routine. */ 309 void *(*start_routine)(void *); 310 void *arg; 311 short mode; 312 NotifierList exit; 313 314 /* Only used for joinable threads. */ 315 bool exited; 316 void *ret; 317 CRITICAL_SECTION cs; 318 }; 319 320 static bool atexit_registered; 321 static NotifierList main_thread_exit; 322 323 static __thread QemuThreadData *qemu_thread_data; 324 325 static void run_main_thread_exit(void) 326 { 327 notifier_list_notify(&main_thread_exit, NULL); 328 } 329 330 void qemu_thread_atexit_add(Notifier *notifier) 331 { 332 if (!qemu_thread_data) { 333 if (!atexit_registered) { 334 atexit_registered = true; 335 atexit(run_main_thread_exit); 336 } 337 notifier_list_add(&main_thread_exit, notifier); 338 } else { 339 notifier_list_add(&qemu_thread_data->exit, notifier); 340 } 341 } 342 343 void qemu_thread_atexit_remove(Notifier *notifier) 344 { 345 notifier_remove(notifier); 346 } 347 348 static unsigned __stdcall win32_start_routine(void *arg) 349 { 350 QemuThreadData *data = (QemuThreadData *) arg; 351 void *(*start_routine)(void *) = data->start_routine; 352 void *thread_arg = data->arg; 353 354 qemu_thread_data = data; 355 qemu_thread_exit(start_routine(thread_arg)); 356 abort(); 357 } 358 359 void qemu_thread_exit(void *arg) 360 { 361 QemuThreadData *data = qemu_thread_data; 362 363 notifier_list_notify(&data->exit, NULL); 364 if (data->mode == QEMU_THREAD_JOINABLE) { 365 data->ret = arg; 366 EnterCriticalSection(&data->cs); 367 data->exited = true; 368 LeaveCriticalSection(&data->cs); 369 } else { 370 g_free(data); 371 } 372 _endthreadex(0); 373 } 374 375 void *qemu_thread_join(QemuThread *thread) 376 { 377 QemuThreadData *data; 378 void *ret; 379 HANDLE handle; 380 381 data = thread->data; 382 if (data->mode == QEMU_THREAD_DETACHED) { 383 return NULL; 384 } 385 386 /* 387 * Because multiple copies of the QemuThread can exist via 388 * qemu_thread_get_self, we need to store a value that cannot 389 * leak there. The simplest, non racy way is to store the TID, 390 * discard the handle that _beginthreadex gives back, and 391 * get another copy of the handle here. 392 */ 393 handle = qemu_thread_get_handle(thread); 394 if (handle) { 395 WaitForSingleObject(handle, INFINITE); 396 CloseHandle(handle); 397 } 398 ret = data->ret; 399 DeleteCriticalSection(&data->cs); 400 g_free(data); 401 return ret; 402 } 403 404 void qemu_thread_create(QemuThread *thread, const char *name, 405 void *(*start_routine)(void *), 406 void *arg, int mode) 407 { 408 HANDLE hThread; 409 struct QemuThreadData *data; 410 411 data = g_malloc(sizeof *data); 412 data->start_routine = start_routine; 413 data->arg = arg; 414 data->mode = mode; 415 data->exited = false; 416 notifier_list_init(&data->exit); 417 418 if (data->mode != QEMU_THREAD_DETACHED) { 419 InitializeCriticalSection(&data->cs); 420 } 421 422 hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine, 423 data, 0, &thread->tid); 424 if (!hThread) { 425 error_exit(GetLastError(), __func__); 426 } 427 CloseHandle(hThread); 428 thread->data = data; 429 } 430 431 void qemu_thread_get_self(QemuThread *thread) 432 { 433 thread->data = qemu_thread_data; 434 thread->tid = GetCurrentThreadId(); 435 } 436 437 HANDLE qemu_thread_get_handle(QemuThread *thread) 438 { 439 QemuThreadData *data; 440 HANDLE handle; 441 442 data = thread->data; 443 if (data->mode == QEMU_THREAD_DETACHED) { 444 return NULL; 445 } 446 447 EnterCriticalSection(&data->cs); 448 if (!data->exited) { 449 handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME | 450 THREAD_SET_CONTEXT, FALSE, thread->tid); 451 } else { 452 handle = NULL; 453 } 454 LeaveCriticalSection(&data->cs); 455 return handle; 456 } 457 458 bool qemu_thread_is_self(QemuThread *thread) 459 { 460 return GetCurrentThreadId() == thread->tid; 461 } 462