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