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