1 /* 2 * Wrappers around mutex/cond/thread functions 3 * 4 * Copyright Red Hat, Inc. 2009 5 * 6 * Author: 7 * Marcelo Tosatti <mtosatti@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/osdep.h" 14 #include "qemu/thread.h" 15 #include "qemu/atomic.h" 16 #include "qemu/notify.h" 17 #include "qemu-thread-common.h" 18 #include "qemu/tsan.h" 19 20 static bool name_threads; 21 22 void qemu_thread_naming(bool enable) 23 { 24 name_threads = enable; 25 26 #if !defined CONFIG_PTHREAD_SETNAME_NP_W_TID && \ 27 !defined CONFIG_PTHREAD_SETNAME_NP_WO_TID 28 /* This is a debugging option, not fatal */ 29 if (enable) { 30 fprintf(stderr, "qemu: thread naming not supported on this host\n"); 31 } 32 #endif 33 } 34 35 static void error_exit(int err, const char *msg) 36 { 37 fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err)); 38 abort(); 39 } 40 41 static void compute_abs_deadline(struct timespec *ts, int ms) 42 { 43 struct timeval tv; 44 gettimeofday(&tv, NULL); 45 ts->tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000; 46 ts->tv_sec = tv.tv_sec + ms / 1000; 47 if (ts->tv_nsec >= 1000000000) { 48 ts->tv_sec++; 49 ts->tv_nsec -= 1000000000; 50 } 51 } 52 53 void qemu_mutex_init(QemuMutex *mutex) 54 { 55 int err; 56 57 err = pthread_mutex_init(&mutex->lock, NULL); 58 if (err) 59 error_exit(err, __func__); 60 qemu_mutex_post_init(mutex); 61 } 62 63 void qemu_mutex_destroy(QemuMutex *mutex) 64 { 65 int err; 66 67 assert(mutex->initialized); 68 mutex->initialized = false; 69 err = pthread_mutex_destroy(&mutex->lock); 70 if (err) 71 error_exit(err, __func__); 72 } 73 74 void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line) 75 { 76 int err; 77 78 assert(mutex->initialized); 79 qemu_mutex_pre_lock(mutex, file, line); 80 err = pthread_mutex_lock(&mutex->lock); 81 if (err) 82 error_exit(err, __func__); 83 qemu_mutex_post_lock(mutex, file, line); 84 } 85 86 int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line) 87 { 88 int err; 89 90 assert(mutex->initialized); 91 err = pthread_mutex_trylock(&mutex->lock); 92 if (err == 0) { 93 qemu_mutex_post_lock(mutex, file, line); 94 return 0; 95 } 96 if (err != EBUSY) { 97 error_exit(err, __func__); 98 } 99 return -EBUSY; 100 } 101 102 void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line) 103 { 104 int err; 105 106 assert(mutex->initialized); 107 qemu_mutex_pre_unlock(mutex, file, line); 108 err = pthread_mutex_unlock(&mutex->lock); 109 if (err) 110 error_exit(err, __func__); 111 } 112 113 void qemu_rec_mutex_init(QemuRecMutex *mutex) 114 { 115 int err; 116 pthread_mutexattr_t attr; 117 118 pthread_mutexattr_init(&attr); 119 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 120 err = pthread_mutex_init(&mutex->m.lock, &attr); 121 pthread_mutexattr_destroy(&attr); 122 if (err) { 123 error_exit(err, __func__); 124 } 125 mutex->m.initialized = true; 126 } 127 128 void qemu_rec_mutex_destroy(QemuRecMutex *mutex) 129 { 130 qemu_mutex_destroy(&mutex->m); 131 } 132 133 void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line) 134 { 135 qemu_mutex_lock_impl(&mutex->m, file, line); 136 } 137 138 int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file, int line) 139 { 140 return qemu_mutex_trylock_impl(&mutex->m, file, line); 141 } 142 143 void qemu_rec_mutex_unlock_impl(QemuRecMutex *mutex, const char *file, int line) 144 { 145 qemu_mutex_unlock_impl(&mutex->m, file, line); 146 } 147 148 void qemu_cond_init(QemuCond *cond) 149 { 150 int err; 151 152 err = pthread_cond_init(&cond->cond, NULL); 153 if (err) 154 error_exit(err, __func__); 155 cond->initialized = true; 156 } 157 158 void qemu_cond_destroy(QemuCond *cond) 159 { 160 int err; 161 162 assert(cond->initialized); 163 cond->initialized = false; 164 err = pthread_cond_destroy(&cond->cond); 165 if (err) 166 error_exit(err, __func__); 167 } 168 169 void qemu_cond_signal(QemuCond *cond) 170 { 171 int err; 172 173 assert(cond->initialized); 174 err = pthread_cond_signal(&cond->cond); 175 if (err) 176 error_exit(err, __func__); 177 } 178 179 void qemu_cond_broadcast(QemuCond *cond) 180 { 181 int err; 182 183 assert(cond->initialized); 184 err = pthread_cond_broadcast(&cond->cond); 185 if (err) 186 error_exit(err, __func__); 187 } 188 189 void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line) 190 { 191 int err; 192 193 assert(cond->initialized); 194 qemu_mutex_pre_unlock(mutex, file, line); 195 err = pthread_cond_wait(&cond->cond, &mutex->lock); 196 qemu_mutex_post_lock(mutex, file, line); 197 if (err) 198 error_exit(err, __func__); 199 } 200 201 bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms, 202 const char *file, const int line) 203 { 204 int err; 205 struct timespec ts; 206 207 assert(cond->initialized); 208 trace_qemu_mutex_unlock(mutex, file, line); 209 compute_abs_deadline(&ts, ms); 210 err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts); 211 trace_qemu_mutex_locked(mutex, file, line); 212 if (err && err != ETIMEDOUT) { 213 error_exit(err, __func__); 214 } 215 return err != ETIMEDOUT; 216 } 217 218 void qemu_sem_init(QemuSemaphore *sem, int init) 219 { 220 int rc; 221 222 #ifndef CONFIG_SEM_TIMEDWAIT 223 rc = pthread_mutex_init(&sem->lock, NULL); 224 if (rc != 0) { 225 error_exit(rc, __func__); 226 } 227 rc = pthread_cond_init(&sem->cond, NULL); 228 if (rc != 0) { 229 error_exit(rc, __func__); 230 } 231 if (init < 0) { 232 error_exit(EINVAL, __func__); 233 } 234 sem->count = init; 235 #else 236 rc = sem_init(&sem->sem, 0, init); 237 if (rc < 0) { 238 error_exit(errno, __func__); 239 } 240 #endif 241 sem->initialized = true; 242 } 243 244 void qemu_sem_destroy(QemuSemaphore *sem) 245 { 246 int rc; 247 248 assert(sem->initialized); 249 sem->initialized = false; 250 #ifndef CONFIG_SEM_TIMEDWAIT 251 rc = pthread_cond_destroy(&sem->cond); 252 if (rc < 0) { 253 error_exit(rc, __func__); 254 } 255 rc = pthread_mutex_destroy(&sem->lock); 256 if (rc < 0) { 257 error_exit(rc, __func__); 258 } 259 #else 260 rc = sem_destroy(&sem->sem); 261 if (rc < 0) { 262 error_exit(errno, __func__); 263 } 264 #endif 265 } 266 267 void qemu_sem_post(QemuSemaphore *sem) 268 { 269 int rc; 270 271 assert(sem->initialized); 272 #ifndef CONFIG_SEM_TIMEDWAIT 273 pthread_mutex_lock(&sem->lock); 274 if (sem->count == UINT_MAX) { 275 rc = EINVAL; 276 } else { 277 sem->count++; 278 rc = pthread_cond_signal(&sem->cond); 279 } 280 pthread_mutex_unlock(&sem->lock); 281 if (rc != 0) { 282 error_exit(rc, __func__); 283 } 284 #else 285 rc = sem_post(&sem->sem); 286 if (rc < 0) { 287 error_exit(errno, __func__); 288 } 289 #endif 290 } 291 292 int qemu_sem_timedwait(QemuSemaphore *sem, int ms) 293 { 294 int rc; 295 struct timespec ts; 296 297 assert(sem->initialized); 298 #ifndef CONFIG_SEM_TIMEDWAIT 299 rc = 0; 300 compute_abs_deadline(&ts, ms); 301 pthread_mutex_lock(&sem->lock); 302 while (sem->count == 0) { 303 rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts); 304 if (rc == ETIMEDOUT) { 305 break; 306 } 307 if (rc != 0) { 308 error_exit(rc, __func__); 309 } 310 } 311 if (rc != ETIMEDOUT) { 312 --sem->count; 313 } 314 pthread_mutex_unlock(&sem->lock); 315 return (rc == ETIMEDOUT ? -1 : 0); 316 #else 317 if (ms <= 0) { 318 /* This is cheaper than sem_timedwait. */ 319 do { 320 rc = sem_trywait(&sem->sem); 321 } while (rc == -1 && errno == EINTR); 322 if (rc == -1 && errno == EAGAIN) { 323 return -1; 324 } 325 } else { 326 compute_abs_deadline(&ts, ms); 327 do { 328 rc = sem_timedwait(&sem->sem, &ts); 329 } while (rc == -1 && errno == EINTR); 330 if (rc == -1 && errno == ETIMEDOUT) { 331 return -1; 332 } 333 } 334 if (rc < 0) { 335 error_exit(errno, __func__); 336 } 337 return 0; 338 #endif 339 } 340 341 void qemu_sem_wait(QemuSemaphore *sem) 342 { 343 int rc; 344 345 assert(sem->initialized); 346 #ifndef CONFIG_SEM_TIMEDWAIT 347 pthread_mutex_lock(&sem->lock); 348 while (sem->count == 0) { 349 rc = pthread_cond_wait(&sem->cond, &sem->lock); 350 if (rc != 0) { 351 error_exit(rc, __func__); 352 } 353 } 354 --sem->count; 355 pthread_mutex_unlock(&sem->lock); 356 #else 357 do { 358 rc = sem_wait(&sem->sem); 359 } while (rc == -1 && errno == EINTR); 360 if (rc < 0) { 361 error_exit(errno, __func__); 362 } 363 #endif 364 } 365 366 #ifdef __linux__ 367 #include "qemu/futex.h" 368 #else 369 static inline void qemu_futex_wake(QemuEvent *ev, int n) 370 { 371 assert(ev->initialized); 372 pthread_mutex_lock(&ev->lock); 373 if (n == 1) { 374 pthread_cond_signal(&ev->cond); 375 } else { 376 pthread_cond_broadcast(&ev->cond); 377 } 378 pthread_mutex_unlock(&ev->lock); 379 } 380 381 static inline void qemu_futex_wait(QemuEvent *ev, unsigned val) 382 { 383 assert(ev->initialized); 384 pthread_mutex_lock(&ev->lock); 385 if (ev->value == val) { 386 pthread_cond_wait(&ev->cond, &ev->lock); 387 } 388 pthread_mutex_unlock(&ev->lock); 389 } 390 #endif 391 392 /* Valid transitions: 393 * - free->set, when setting the event 394 * - busy->set, when setting the event, followed by qemu_futex_wake 395 * - set->free, when resetting the event 396 * - free->busy, when waiting 397 * 398 * set->busy does not happen (it can be observed from the outside but 399 * it really is set->free->busy). 400 * 401 * busy->free provably cannot happen; to enforce it, the set->free transition 402 * is done with an OR, which becomes a no-op if the event has concurrently 403 * transitioned to free or busy. 404 */ 405 406 #define EV_SET 0 407 #define EV_FREE 1 408 #define EV_BUSY -1 409 410 void qemu_event_init(QemuEvent *ev, bool init) 411 { 412 #ifndef __linux__ 413 pthread_mutex_init(&ev->lock, NULL); 414 pthread_cond_init(&ev->cond, NULL); 415 #endif 416 417 ev->value = (init ? EV_SET : EV_FREE); 418 ev->initialized = true; 419 } 420 421 void qemu_event_destroy(QemuEvent *ev) 422 { 423 assert(ev->initialized); 424 ev->initialized = false; 425 #ifndef __linux__ 426 pthread_mutex_destroy(&ev->lock); 427 pthread_cond_destroy(&ev->cond); 428 #endif 429 } 430 431 void qemu_event_set(QemuEvent *ev) 432 { 433 /* qemu_event_set has release semantics, but because it *loads* 434 * ev->value we need a full memory barrier here. 435 */ 436 assert(ev->initialized); 437 smp_mb(); 438 if (qatomic_read(&ev->value) != EV_SET) { 439 if (qatomic_xchg(&ev->value, EV_SET) == EV_BUSY) { 440 /* There were waiters, wake them up. */ 441 qemu_futex_wake(ev, INT_MAX); 442 } 443 } 444 } 445 446 void qemu_event_reset(QemuEvent *ev) 447 { 448 unsigned value; 449 450 assert(ev->initialized); 451 value = qatomic_read(&ev->value); 452 smp_mb_acquire(); 453 if (value == EV_SET) { 454 /* 455 * If there was a concurrent reset (or even reset+wait), 456 * do nothing. Otherwise change EV_SET->EV_FREE. 457 */ 458 qatomic_or(&ev->value, EV_FREE); 459 } 460 } 461 462 void qemu_event_wait(QemuEvent *ev) 463 { 464 unsigned value; 465 466 assert(ev->initialized); 467 value = qatomic_read(&ev->value); 468 smp_mb_acquire(); 469 if (value != EV_SET) { 470 if (value == EV_FREE) { 471 /* 472 * Leave the event reset and tell qemu_event_set that there 473 * are waiters. No need to retry, because there cannot be 474 * a concurrent busy->free transition. After the CAS, the 475 * event will be either set or busy. 476 */ 477 if (qatomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { 478 return; 479 } 480 } 481 qemu_futex_wait(ev, EV_BUSY); 482 } 483 } 484 485 static __thread NotifierList thread_exit; 486 487 /* 488 * Note that in this implementation you can register a thread-exit 489 * notifier for the main thread, but it will never be called. 490 * This is OK because main thread exit can only happen when the 491 * entire process is exiting, and the API allows notifiers to not 492 * be called on process exit. 493 */ 494 void qemu_thread_atexit_add(Notifier *notifier) 495 { 496 notifier_list_add(&thread_exit, notifier); 497 } 498 499 void qemu_thread_atexit_remove(Notifier *notifier) 500 { 501 notifier_remove(notifier); 502 } 503 504 static void qemu_thread_atexit_notify(void *arg) 505 { 506 /* 507 * Called when non-main thread exits (via qemu_thread_exit() 508 * or by returning from its start routine.) 509 */ 510 notifier_list_notify(&thread_exit, NULL); 511 } 512 513 typedef struct { 514 void *(*start_routine)(void *); 515 void *arg; 516 char *name; 517 } QemuThreadArgs; 518 519 static void *qemu_thread_start(void *args) 520 { 521 QemuThreadArgs *qemu_thread_args = args; 522 void *(*start_routine)(void *) = qemu_thread_args->start_routine; 523 void *arg = qemu_thread_args->arg; 524 void *r; 525 526 /* Attempt to set the threads name; note that this is for debug, so 527 * we're not going to fail if we can't set it. 528 */ 529 if (name_threads && qemu_thread_args->name) { 530 # if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID) 531 pthread_setname_np(pthread_self(), qemu_thread_args->name); 532 # elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID) 533 pthread_setname_np(qemu_thread_args->name); 534 # endif 535 } 536 QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name); 537 g_free(qemu_thread_args->name); 538 g_free(qemu_thread_args); 539 540 /* 541 * GCC 11 with glibc 2.17 on PowerPC reports 542 * 543 * qemu-thread-posix.c:540:5: error: ‘__sigsetjmp’ accessing 656 bytes 544 * in a region of size 528 [-Werror=stringop-overflow=] 545 * 540 | pthread_cleanup_push(qemu_thread_atexit_notify, NULL); 546 * | ^~~~~~~~~~~~~~~~~~~~ 547 * 548 * which is clearly nonsense. 549 */ 550 #pragma GCC diagnostic push 551 #ifndef __clang__ 552 #pragma GCC diagnostic ignored "-Wstringop-overflow" 553 #endif 554 555 pthread_cleanup_push(qemu_thread_atexit_notify, NULL); 556 r = start_routine(arg); 557 pthread_cleanup_pop(1); 558 559 #pragma GCC diagnostic pop 560 561 return r; 562 } 563 564 void qemu_thread_create(QemuThread *thread, const char *name, 565 void *(*start_routine)(void*), 566 void *arg, int mode) 567 { 568 sigset_t set, oldset; 569 int err; 570 pthread_attr_t attr; 571 QemuThreadArgs *qemu_thread_args; 572 573 err = pthread_attr_init(&attr); 574 if (err) { 575 error_exit(err, __func__); 576 } 577 578 if (mode == QEMU_THREAD_DETACHED) { 579 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 580 } 581 582 /* Leave signal handling to the iothread. */ 583 sigfillset(&set); 584 /* Blocking the signals can result in undefined behaviour. */ 585 sigdelset(&set, SIGSEGV); 586 sigdelset(&set, SIGFPE); 587 sigdelset(&set, SIGILL); 588 /* TODO avoid SIGBUS loss on macOS */ 589 pthread_sigmask(SIG_SETMASK, &set, &oldset); 590 591 qemu_thread_args = g_new0(QemuThreadArgs, 1); 592 qemu_thread_args->name = g_strdup(name); 593 qemu_thread_args->start_routine = start_routine; 594 qemu_thread_args->arg = arg; 595 596 err = pthread_create(&thread->thread, &attr, 597 qemu_thread_start, qemu_thread_args); 598 599 if (err) 600 error_exit(err, __func__); 601 602 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 603 604 pthread_attr_destroy(&attr); 605 } 606 607 void qemu_thread_get_self(QemuThread *thread) 608 { 609 thread->thread = pthread_self(); 610 } 611 612 bool qemu_thread_is_self(QemuThread *thread) 613 { 614 return pthread_equal(pthread_self(), thread->thread); 615 } 616 617 void qemu_thread_exit(void *retval) 618 { 619 pthread_exit(retval); 620 } 621 622 void *qemu_thread_join(QemuThread *thread) 623 { 624 int err; 625 void *ret; 626 627 err = pthread_join(thread->thread, &ret); 628 if (err) { 629 error_exit(err, __func__); 630 } 631 return ret; 632 } 633