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 "trace.h" 18 19 static bool name_threads; 20 21 void qemu_thread_naming(bool enable) 22 { 23 name_threads = enable; 24 25 #ifndef CONFIG_THREAD_SETNAME_BYTHREAD 26 /* This is a debugging option, not fatal */ 27 if (enable) { 28 fprintf(stderr, "qemu: thread naming not supported on this host\n"); 29 } 30 #endif 31 } 32 33 static void error_exit(int err, const char *msg) 34 { 35 fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err)); 36 abort(); 37 } 38 39 void qemu_mutex_init(QemuMutex *mutex) 40 { 41 int err; 42 43 err = pthread_mutex_init(&mutex->lock, NULL); 44 if (err) 45 error_exit(err, __func__); 46 mutex->initialized = true; 47 } 48 49 void qemu_mutex_destroy(QemuMutex *mutex) 50 { 51 int err; 52 53 assert(mutex->initialized); 54 mutex->initialized = false; 55 err = pthread_mutex_destroy(&mutex->lock); 56 if (err) 57 error_exit(err, __func__); 58 } 59 60 void qemu_mutex_lock(QemuMutex *mutex) 61 { 62 int err; 63 64 assert(mutex->initialized); 65 err = pthread_mutex_lock(&mutex->lock); 66 if (err) 67 error_exit(err, __func__); 68 69 trace_qemu_mutex_locked(mutex); 70 } 71 72 int qemu_mutex_trylock(QemuMutex *mutex) 73 { 74 int err; 75 76 assert(mutex->initialized); 77 err = pthread_mutex_trylock(&mutex->lock); 78 if (err == 0) { 79 trace_qemu_mutex_locked(mutex); 80 return 0; 81 } 82 if (err != EBUSY) { 83 error_exit(err, __func__); 84 } 85 return -EBUSY; 86 } 87 88 void qemu_mutex_unlock(QemuMutex *mutex) 89 { 90 int err; 91 92 assert(mutex->initialized); 93 trace_qemu_mutex_unlocked(mutex); 94 err = pthread_mutex_unlock(&mutex->lock); 95 if (err) 96 error_exit(err, __func__); 97 } 98 99 void qemu_rec_mutex_init(QemuRecMutex *mutex) 100 { 101 int err; 102 pthread_mutexattr_t attr; 103 104 pthread_mutexattr_init(&attr); 105 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 106 err = pthread_mutex_init(&mutex->lock, &attr); 107 pthread_mutexattr_destroy(&attr); 108 if (err) { 109 error_exit(err, __func__); 110 } 111 mutex->initialized = true; 112 } 113 114 void qemu_cond_init(QemuCond *cond) 115 { 116 int err; 117 118 err = pthread_cond_init(&cond->cond, NULL); 119 if (err) 120 error_exit(err, __func__); 121 cond->initialized = true; 122 } 123 124 void qemu_cond_destroy(QemuCond *cond) 125 { 126 int err; 127 128 assert(cond->initialized); 129 cond->initialized = false; 130 err = pthread_cond_destroy(&cond->cond); 131 if (err) 132 error_exit(err, __func__); 133 } 134 135 void qemu_cond_signal(QemuCond *cond) 136 { 137 int err; 138 139 assert(cond->initialized); 140 err = pthread_cond_signal(&cond->cond); 141 if (err) 142 error_exit(err, __func__); 143 } 144 145 void qemu_cond_broadcast(QemuCond *cond) 146 { 147 int err; 148 149 assert(cond->initialized); 150 err = pthread_cond_broadcast(&cond->cond); 151 if (err) 152 error_exit(err, __func__); 153 } 154 155 void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex) 156 { 157 int err; 158 159 assert(cond->initialized); 160 trace_qemu_mutex_unlocked(mutex); 161 err = pthread_cond_wait(&cond->cond, &mutex->lock); 162 trace_qemu_mutex_locked(mutex); 163 if (err) 164 error_exit(err, __func__); 165 } 166 167 void qemu_sem_init(QemuSemaphore *sem, int init) 168 { 169 int rc; 170 171 #ifndef CONFIG_SEM_TIMEDWAIT 172 rc = pthread_mutex_init(&sem->lock, NULL); 173 if (rc != 0) { 174 error_exit(rc, __func__); 175 } 176 rc = pthread_cond_init(&sem->cond, NULL); 177 if (rc != 0) { 178 error_exit(rc, __func__); 179 } 180 if (init < 0) { 181 error_exit(EINVAL, __func__); 182 } 183 sem->count = init; 184 #else 185 rc = sem_init(&sem->sem, 0, init); 186 if (rc < 0) { 187 error_exit(errno, __func__); 188 } 189 #endif 190 sem->initialized = true; 191 } 192 193 void qemu_sem_destroy(QemuSemaphore *sem) 194 { 195 int rc; 196 197 assert(sem->initialized); 198 sem->initialized = false; 199 #ifndef CONFIG_SEM_TIMEDWAIT 200 rc = pthread_cond_destroy(&sem->cond); 201 if (rc < 0) { 202 error_exit(rc, __func__); 203 } 204 rc = pthread_mutex_destroy(&sem->lock); 205 if (rc < 0) { 206 error_exit(rc, __func__); 207 } 208 #else 209 rc = sem_destroy(&sem->sem); 210 if (rc < 0) { 211 error_exit(errno, __func__); 212 } 213 #endif 214 } 215 216 void qemu_sem_post(QemuSemaphore *sem) 217 { 218 int rc; 219 220 assert(sem->initialized); 221 #ifndef CONFIG_SEM_TIMEDWAIT 222 pthread_mutex_lock(&sem->lock); 223 if (sem->count == UINT_MAX) { 224 rc = EINVAL; 225 } else { 226 sem->count++; 227 rc = pthread_cond_signal(&sem->cond); 228 } 229 pthread_mutex_unlock(&sem->lock); 230 if (rc != 0) { 231 error_exit(rc, __func__); 232 } 233 #else 234 rc = sem_post(&sem->sem); 235 if (rc < 0) { 236 error_exit(errno, __func__); 237 } 238 #endif 239 } 240 241 static void compute_abs_deadline(struct timespec *ts, int ms) 242 { 243 struct timeval tv; 244 gettimeofday(&tv, NULL); 245 ts->tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000; 246 ts->tv_sec = tv.tv_sec + ms / 1000; 247 if (ts->tv_nsec >= 1000000000) { 248 ts->tv_sec++; 249 ts->tv_nsec -= 1000000000; 250 } 251 } 252 253 int qemu_sem_timedwait(QemuSemaphore *sem, int ms) 254 { 255 int rc; 256 struct timespec ts; 257 258 assert(sem->initialized); 259 #ifndef CONFIG_SEM_TIMEDWAIT 260 rc = 0; 261 compute_abs_deadline(&ts, ms); 262 pthread_mutex_lock(&sem->lock); 263 while (sem->count == 0) { 264 rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts); 265 if (rc == ETIMEDOUT) { 266 break; 267 } 268 if (rc != 0) { 269 error_exit(rc, __func__); 270 } 271 } 272 if (rc != ETIMEDOUT) { 273 --sem->count; 274 } 275 pthread_mutex_unlock(&sem->lock); 276 return (rc == ETIMEDOUT ? -1 : 0); 277 #else 278 if (ms <= 0) { 279 /* This is cheaper than sem_timedwait. */ 280 do { 281 rc = sem_trywait(&sem->sem); 282 } while (rc == -1 && errno == EINTR); 283 if (rc == -1 && errno == EAGAIN) { 284 return -1; 285 } 286 } else { 287 compute_abs_deadline(&ts, ms); 288 do { 289 rc = sem_timedwait(&sem->sem, &ts); 290 } while (rc == -1 && errno == EINTR); 291 if (rc == -1 && errno == ETIMEDOUT) { 292 return -1; 293 } 294 } 295 if (rc < 0) { 296 error_exit(errno, __func__); 297 } 298 return 0; 299 #endif 300 } 301 302 void qemu_sem_wait(QemuSemaphore *sem) 303 { 304 int rc; 305 306 assert(sem->initialized); 307 #ifndef CONFIG_SEM_TIMEDWAIT 308 pthread_mutex_lock(&sem->lock); 309 while (sem->count == 0) { 310 rc = pthread_cond_wait(&sem->cond, &sem->lock); 311 if (rc != 0) { 312 error_exit(rc, __func__); 313 } 314 } 315 --sem->count; 316 pthread_mutex_unlock(&sem->lock); 317 #else 318 do { 319 rc = sem_wait(&sem->sem); 320 } while (rc == -1 && errno == EINTR); 321 if (rc < 0) { 322 error_exit(errno, __func__); 323 } 324 #endif 325 } 326 327 #ifdef __linux__ 328 #include "qemu/futex.h" 329 #else 330 static inline void qemu_futex_wake(QemuEvent *ev, int n) 331 { 332 assert(ev->initialized); 333 pthread_mutex_lock(&ev->lock); 334 if (n == 1) { 335 pthread_cond_signal(&ev->cond); 336 } else { 337 pthread_cond_broadcast(&ev->cond); 338 } 339 pthread_mutex_unlock(&ev->lock); 340 } 341 342 static inline void qemu_futex_wait(QemuEvent *ev, unsigned val) 343 { 344 assert(ev->initialized); 345 pthread_mutex_lock(&ev->lock); 346 if (ev->value == val) { 347 pthread_cond_wait(&ev->cond, &ev->lock); 348 } 349 pthread_mutex_unlock(&ev->lock); 350 } 351 #endif 352 353 /* Valid transitions: 354 * - free->set, when setting the event 355 * - busy->set, when setting the event, followed by qemu_futex_wake 356 * - set->free, when resetting the event 357 * - free->busy, when waiting 358 * 359 * set->busy does not happen (it can be observed from the outside but 360 * it really is set->free->busy). 361 * 362 * busy->free provably cannot happen; to enforce it, the set->free transition 363 * is done with an OR, which becomes a no-op if the event has concurrently 364 * transitioned to free or busy. 365 */ 366 367 #define EV_SET 0 368 #define EV_FREE 1 369 #define EV_BUSY -1 370 371 void qemu_event_init(QemuEvent *ev, bool init) 372 { 373 #ifndef __linux__ 374 pthread_mutex_init(&ev->lock, NULL); 375 pthread_cond_init(&ev->cond, NULL); 376 #endif 377 378 ev->value = (init ? EV_SET : EV_FREE); 379 ev->initialized = true; 380 } 381 382 void qemu_event_destroy(QemuEvent *ev) 383 { 384 assert(ev->initialized); 385 ev->initialized = false; 386 #ifndef __linux__ 387 pthread_mutex_destroy(&ev->lock); 388 pthread_cond_destroy(&ev->cond); 389 #endif 390 } 391 392 void qemu_event_set(QemuEvent *ev) 393 { 394 /* qemu_event_set has release semantics, but because it *loads* 395 * ev->value we need a full memory barrier here. 396 */ 397 assert(ev->initialized); 398 smp_mb(); 399 if (atomic_read(&ev->value) != EV_SET) { 400 if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) { 401 /* There were waiters, wake them up. */ 402 qemu_futex_wake(ev, INT_MAX); 403 } 404 } 405 } 406 407 void qemu_event_reset(QemuEvent *ev) 408 { 409 unsigned value; 410 411 assert(ev->initialized); 412 value = atomic_read(&ev->value); 413 smp_mb_acquire(); 414 if (value == EV_SET) { 415 /* 416 * If there was a concurrent reset (or even reset+wait), 417 * do nothing. Otherwise change EV_SET->EV_FREE. 418 */ 419 atomic_or(&ev->value, EV_FREE); 420 } 421 } 422 423 void qemu_event_wait(QemuEvent *ev) 424 { 425 unsigned value; 426 427 assert(ev->initialized); 428 value = atomic_read(&ev->value); 429 smp_mb_acquire(); 430 if (value != EV_SET) { 431 if (value == EV_FREE) { 432 /* 433 * Leave the event reset and tell qemu_event_set that there 434 * are waiters. No need to retry, because there cannot be 435 * a concurrent busy->free transition. After the CAS, the 436 * event will be either set or busy. 437 */ 438 if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) { 439 return; 440 } 441 } 442 qemu_futex_wait(ev, EV_BUSY); 443 } 444 } 445 446 static pthread_key_t exit_key; 447 448 union NotifierThreadData { 449 void *ptr; 450 NotifierList list; 451 }; 452 QEMU_BUILD_BUG_ON(sizeof(union NotifierThreadData) != sizeof(void *)); 453 454 void qemu_thread_atexit_add(Notifier *notifier) 455 { 456 union NotifierThreadData ntd; 457 ntd.ptr = pthread_getspecific(exit_key); 458 notifier_list_add(&ntd.list, notifier); 459 pthread_setspecific(exit_key, ntd.ptr); 460 } 461 462 void qemu_thread_atexit_remove(Notifier *notifier) 463 { 464 union NotifierThreadData ntd; 465 ntd.ptr = pthread_getspecific(exit_key); 466 notifier_remove(notifier); 467 pthread_setspecific(exit_key, ntd.ptr); 468 } 469 470 static void qemu_thread_atexit_run(void *arg) 471 { 472 union NotifierThreadData ntd = { .ptr = arg }; 473 notifier_list_notify(&ntd.list, NULL); 474 } 475 476 static void __attribute__((constructor)) qemu_thread_atexit_init(void) 477 { 478 pthread_key_create(&exit_key, qemu_thread_atexit_run); 479 } 480 481 482 /* Attempt to set the threads name; note that this is for debug, so 483 * we're not going to fail if we can't set it. 484 */ 485 static void qemu_thread_set_name(QemuThread *thread, const char *name) 486 { 487 #ifdef CONFIG_PTHREAD_SETNAME_NP 488 pthread_setname_np(thread->thread, name); 489 #endif 490 } 491 492 void qemu_thread_create(QemuThread *thread, const char *name, 493 void *(*start_routine)(void*), 494 void *arg, int mode) 495 { 496 sigset_t set, oldset; 497 int err; 498 pthread_attr_t attr; 499 500 err = pthread_attr_init(&attr); 501 if (err) { 502 error_exit(err, __func__); 503 } 504 505 /* Leave signal handling to the iothread. */ 506 sigfillset(&set); 507 pthread_sigmask(SIG_SETMASK, &set, &oldset); 508 err = pthread_create(&thread->thread, &attr, start_routine, arg); 509 if (err) 510 error_exit(err, __func__); 511 512 if (name_threads) { 513 qemu_thread_set_name(thread, name); 514 } 515 516 if (mode == QEMU_THREAD_DETACHED) { 517 err = pthread_detach(thread->thread); 518 if (err) { 519 error_exit(err, __func__); 520 } 521 } 522 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 523 524 pthread_attr_destroy(&attr); 525 } 526 527 void qemu_thread_get_self(QemuThread *thread) 528 { 529 thread->thread = pthread_self(); 530 } 531 532 bool qemu_thread_is_self(QemuThread *thread) 533 { 534 return pthread_equal(pthread_self(), thread->thread); 535 } 536 537 void qemu_thread_exit(void *retval) 538 { 539 pthread_exit(retval); 540 } 541 542 void *qemu_thread_join(QemuThread *thread) 543 { 544 int err; 545 void *ret; 546 547 err = pthread_join(thread->thread, &ret); 548 if (err) { 549 error_exit(err, __func__); 550 } 551 return ret; 552 } 553