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 #include "qemu-common.h" 14 #include "qemu/thread.h" 15 #include "qemu/notify.h" 16 #include <process.h> 17 #include <assert.h> 18 #include <limits.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 mutex->owner = 0; 44 InitializeCriticalSection(&mutex->lock); 45 } 46 47 void qemu_mutex_destroy(QemuMutex *mutex) 48 { 49 assert(mutex->owner == 0); 50 DeleteCriticalSection(&mutex->lock); 51 } 52 53 void qemu_mutex_lock(QemuMutex *mutex) 54 { 55 EnterCriticalSection(&mutex->lock); 56 57 /* Win32 CRITICAL_SECTIONs are recursive. Assert that we're not 58 * using them as such. 59 */ 60 assert(mutex->owner == 0); 61 mutex->owner = GetCurrentThreadId(); 62 } 63 64 int qemu_mutex_trylock(QemuMutex *mutex) 65 { 66 int owned; 67 68 owned = TryEnterCriticalSection(&mutex->lock); 69 if (owned) { 70 assert(mutex->owner == 0); 71 mutex->owner = GetCurrentThreadId(); 72 } 73 return !owned; 74 } 75 76 void qemu_mutex_unlock(QemuMutex *mutex) 77 { 78 assert(mutex->owner == GetCurrentThreadId()); 79 mutex->owner = 0; 80 LeaveCriticalSection(&mutex->lock); 81 } 82 83 void qemu_cond_init(QemuCond *cond) 84 { 85 memset(cond, 0, sizeof(*cond)); 86 87 cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL); 88 if (!cond->sema) { 89 error_exit(GetLastError(), __func__); 90 } 91 cond->continue_event = CreateEvent(NULL, /* security */ 92 FALSE, /* auto-reset */ 93 FALSE, /* not signaled */ 94 NULL); /* name */ 95 if (!cond->continue_event) { 96 error_exit(GetLastError(), __func__); 97 } 98 } 99 100 void qemu_cond_destroy(QemuCond *cond) 101 { 102 BOOL result; 103 result = CloseHandle(cond->continue_event); 104 if (!result) { 105 error_exit(GetLastError(), __func__); 106 } 107 cond->continue_event = 0; 108 result = CloseHandle(cond->sema); 109 if (!result) { 110 error_exit(GetLastError(), __func__); 111 } 112 cond->sema = 0; 113 } 114 115 void qemu_cond_signal(QemuCond *cond) 116 { 117 DWORD result; 118 119 /* 120 * Signal only when there are waiters. cond->waiters is 121 * incremented by pthread_cond_wait under the external lock, 122 * so we are safe about that. 123 */ 124 if (cond->waiters == 0) { 125 return; 126 } 127 128 /* 129 * Waiting threads decrement it outside the external lock, but 130 * only if another thread is executing pthread_cond_broadcast and 131 * has the mutex. So, it also cannot be decremented concurrently 132 * with this particular access. 133 */ 134 cond->target = cond->waiters - 1; 135 result = SignalObjectAndWait(cond->sema, cond->continue_event, 136 INFINITE, FALSE); 137 if (result == WAIT_ABANDONED || result == WAIT_FAILED) { 138 error_exit(GetLastError(), __func__); 139 } 140 } 141 142 void qemu_cond_broadcast(QemuCond *cond) 143 { 144 BOOLEAN result; 145 /* 146 * As in pthread_cond_signal, access to cond->waiters and 147 * cond->target is locked via the external mutex. 148 */ 149 if (cond->waiters == 0) { 150 return; 151 } 152 153 cond->target = 0; 154 result = ReleaseSemaphore(cond->sema, cond->waiters, NULL); 155 if (!result) { 156 error_exit(GetLastError(), __func__); 157 } 158 159 /* 160 * At this point all waiters continue. Each one takes its 161 * slice of the semaphore. Now it's our turn to wait: Since 162 * the external mutex is held, no thread can leave cond_wait, 163 * yet. For this reason, we can be sure that no thread gets 164 * a chance to eat *more* than one slice. OTOH, it means 165 * that the last waiter must send us a wake-up. 166 */ 167 WaitForSingleObject(cond->continue_event, INFINITE); 168 } 169 170 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) 171 { 172 /* 173 * This access is protected under the mutex. 174 */ 175 cond->waiters++; 176 177 /* 178 * Unlock external mutex and wait for signal. 179 * NOTE: we've held mutex locked long enough to increment 180 * waiters count above, so there's no problem with 181 * leaving mutex unlocked before we wait on semaphore. 182 */ 183 qemu_mutex_unlock(mutex); 184 WaitForSingleObject(cond->sema, INFINITE); 185 186 /* Now waiters must rendez-vous with the signaling thread and 187 * let it continue. For cond_broadcast this has heavy contention 188 * and triggers thundering herd. So goes life. 189 * 190 * Decrease waiters count. The mutex is not taken, so we have 191 * to do this atomically. 192 * 193 * All waiters contend for the mutex at the end of this function 194 * until the signaling thread relinquishes it. To ensure 195 * each waiter consumes exactly one slice of the semaphore, 196 * the signaling thread stops until it is told by the last 197 * waiter that it can go on. 198 */ 199 if (InterlockedDecrement(&cond->waiters) == cond->target) { 200 SetEvent(cond->continue_event); 201 } 202 203 qemu_mutex_lock(mutex); 204 } 205 206 void qemu_sem_init(QemuSemaphore *sem, int init) 207 { 208 /* Manual reset. */ 209 sem->sema = CreateSemaphore(NULL, init, LONG_MAX, NULL); 210 } 211 212 void qemu_sem_destroy(QemuSemaphore *sem) 213 { 214 CloseHandle(sem->sema); 215 } 216 217 void qemu_sem_post(QemuSemaphore *sem) 218 { 219 ReleaseSemaphore(sem->sema, 1, NULL); 220 } 221 222 int qemu_sem_timedwait(QemuSemaphore *sem, int ms) 223 { 224 int rc = WaitForSingleObject(sem->sema, ms); 225 if (rc == WAIT_OBJECT_0) { 226 return 0; 227 } 228 if (rc != WAIT_TIMEOUT) { 229 error_exit(GetLastError(), __func__); 230 } 231 return -1; 232 } 233 234 void qemu_sem_wait(QemuSemaphore *sem) 235 { 236 if (WaitForSingleObject(sem->sema, INFINITE) != WAIT_OBJECT_0) { 237 error_exit(GetLastError(), __func__); 238 } 239 } 240 241 void qemu_event_init(QemuEvent *ev, bool init) 242 { 243 /* Manual reset. */ 244 ev->event = CreateEvent(NULL, TRUE, init, NULL); 245 } 246 247 void qemu_event_destroy(QemuEvent *ev) 248 { 249 CloseHandle(ev->event); 250 } 251 252 void qemu_event_set(QemuEvent *ev) 253 { 254 SetEvent(ev->event); 255 } 256 257 void qemu_event_reset(QemuEvent *ev) 258 { 259 ResetEvent(ev->event); 260 } 261 262 void qemu_event_wait(QemuEvent *ev) 263 { 264 WaitForSingleObject(ev->event, INFINITE); 265 } 266 267 struct QemuThreadData { 268 /* Passed to win32_start_routine. */ 269 void *(*start_routine)(void *); 270 void *arg; 271 short mode; 272 NotifierList exit; 273 274 /* Only used for joinable threads. */ 275 bool exited; 276 void *ret; 277 CRITICAL_SECTION cs; 278 }; 279 280 static bool atexit_registered; 281 static NotifierList main_thread_exit; 282 283 static __thread QemuThreadData *qemu_thread_data; 284 285 static void run_main_thread_exit(void) 286 { 287 notifier_list_notify(&main_thread_exit, NULL); 288 } 289 290 void qemu_thread_atexit_add(Notifier *notifier) 291 { 292 if (!qemu_thread_data) { 293 if (!atexit_registered) { 294 atexit_registered = true; 295 atexit(run_main_thread_exit); 296 } 297 notifier_list_add(&main_thread_exit, notifier); 298 } else { 299 notifier_list_add(&qemu_thread_data->exit, notifier); 300 } 301 } 302 303 void qemu_thread_atexit_remove(Notifier *notifier) 304 { 305 notifier_remove(notifier); 306 } 307 308 static unsigned __stdcall win32_start_routine(void *arg) 309 { 310 QemuThreadData *data = (QemuThreadData *) arg; 311 void *(*start_routine)(void *) = data->start_routine; 312 void *thread_arg = data->arg; 313 314 qemu_thread_data = data; 315 qemu_thread_exit(start_routine(thread_arg)); 316 abort(); 317 } 318 319 void qemu_thread_exit(void *arg) 320 { 321 QemuThreadData *data = qemu_thread_data; 322 323 notifier_list_notify(&data->exit, NULL); 324 if (data->mode == QEMU_THREAD_JOINABLE) { 325 data->ret = arg; 326 EnterCriticalSection(&data->cs); 327 data->exited = true; 328 LeaveCriticalSection(&data->cs); 329 } else { 330 g_free(data); 331 } 332 _endthreadex(0); 333 } 334 335 void *qemu_thread_join(QemuThread *thread) 336 { 337 QemuThreadData *data; 338 void *ret; 339 HANDLE handle; 340 341 data = thread->data; 342 if (data->mode == QEMU_THREAD_DETACHED) { 343 return NULL; 344 } 345 346 /* 347 * Because multiple copies of the QemuThread can exist via 348 * qemu_thread_get_self, we need to store a value that cannot 349 * leak there. The simplest, non racy way is to store the TID, 350 * discard the handle that _beginthreadex gives back, and 351 * get another copy of the handle here. 352 */ 353 handle = qemu_thread_get_handle(thread); 354 if (handle) { 355 WaitForSingleObject(handle, INFINITE); 356 CloseHandle(handle); 357 } 358 ret = data->ret; 359 DeleteCriticalSection(&data->cs); 360 g_free(data); 361 return ret; 362 } 363 364 void qemu_thread_create(QemuThread *thread, const char *name, 365 void *(*start_routine)(void *), 366 void *arg, int mode) 367 { 368 HANDLE hThread; 369 struct QemuThreadData *data; 370 371 data = g_malloc(sizeof *data); 372 data->start_routine = start_routine; 373 data->arg = arg; 374 data->mode = mode; 375 data->exited = false; 376 notifier_list_init(&data->exit); 377 378 if (data->mode != QEMU_THREAD_DETACHED) { 379 InitializeCriticalSection(&data->cs); 380 } 381 382 hThread = (HANDLE) _beginthreadex(NULL, 0, win32_start_routine, 383 data, 0, &thread->tid); 384 if (!hThread) { 385 error_exit(GetLastError(), __func__); 386 } 387 CloseHandle(hThread); 388 thread->data = data; 389 } 390 391 void qemu_thread_get_self(QemuThread *thread) 392 { 393 thread->data = qemu_thread_data; 394 thread->tid = GetCurrentThreadId(); 395 } 396 397 HANDLE qemu_thread_get_handle(QemuThread *thread) 398 { 399 QemuThreadData *data; 400 HANDLE handle; 401 402 data = thread->data; 403 if (data->mode == QEMU_THREAD_DETACHED) { 404 return NULL; 405 } 406 407 EnterCriticalSection(&data->cs); 408 if (!data->exited) { 409 handle = OpenThread(SYNCHRONIZE | THREAD_SUSPEND_RESUME, FALSE, 410 thread->tid); 411 } else { 412 handle = NULL; 413 } 414 LeaveCriticalSection(&data->cs); 415 return handle; 416 } 417 418 bool qemu_thread_is_self(QemuThread *thread) 419 { 420 return GetCurrentThreadId() == thread->tid; 421 } 422