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