2 * Wrappers around mutex/cond/thread functions
4 * Copyright Red Hat, Inc. 2009
7 * Marcelo Tosatti <mtosatti@redhat.com>
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.
13 #include "qemu/osdep.h"
15 #include <sys/syscall.h>
16 #include <linux/futex.h>
18 #include "qemu/thread.h"
19 #include "qemu/atomic.h"
20 #include "qemu/notify.h"
22 static bool name_threads
;
24 void qemu_thread_naming(bool enable
)
26 name_threads
= enable
;
28 #ifndef CONFIG_THREAD_SETNAME_BYTHREAD
29 /* This is a debugging option, not fatal */
31 fprintf(stderr
, "qemu: thread naming not supported on this host\n");
36 static void error_exit(int err
, const char *msg
)
38 fprintf(stderr
, "qemu: %s: %s\n", msg
, strerror(err
));
42 void qemu_mutex_init(QemuMutex
*mutex
)
46 err
= pthread_mutex_init(&mutex
->lock
, NULL
);
48 error_exit(err
, __func__
);
51 void qemu_mutex_destroy(QemuMutex
*mutex
)
55 err
= pthread_mutex_destroy(&mutex
->lock
);
57 error_exit(err
, __func__
);
60 void qemu_mutex_lock(QemuMutex
*mutex
)
64 err
= pthread_mutex_lock(&mutex
->lock
);
66 error_exit(err
, __func__
);
69 int qemu_mutex_trylock(QemuMutex
*mutex
)
71 return pthread_mutex_trylock(&mutex
->lock
);
74 void qemu_mutex_unlock(QemuMutex
*mutex
)
78 err
= pthread_mutex_unlock(&mutex
->lock
);
80 error_exit(err
, __func__
);
83 void qemu_rec_mutex_init(QemuRecMutex
*mutex
)
86 pthread_mutexattr_t attr
;
88 pthread_mutexattr_init(&attr
);
89 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
);
90 err
= pthread_mutex_init(&mutex
->lock
, &attr
);
91 pthread_mutexattr_destroy(&attr
);
93 error_exit(err
, __func__
);
97 void qemu_cond_init(QemuCond
*cond
)
101 err
= pthread_cond_init(&cond
->cond
, NULL
);
103 error_exit(err
, __func__
);
106 void qemu_cond_destroy(QemuCond
*cond
)
110 err
= pthread_cond_destroy(&cond
->cond
);
112 error_exit(err
, __func__
);
115 void qemu_cond_signal(QemuCond
*cond
)
119 err
= pthread_cond_signal(&cond
->cond
);
121 error_exit(err
, __func__
);
124 void qemu_cond_broadcast(QemuCond
*cond
)
128 err
= pthread_cond_broadcast(&cond
->cond
);
130 error_exit(err
, __func__
);
133 void qemu_cond_wait(QemuCond
*cond
, QemuMutex
*mutex
)
137 err
= pthread_cond_wait(&cond
->cond
, &mutex
->lock
);
139 error_exit(err
, __func__
);
142 void qemu_sem_init(QemuSemaphore
*sem
, int init
)
146 #if defined(__APPLE__) || defined(__NetBSD__)
147 rc
= pthread_mutex_init(&sem
->lock
, NULL
);
149 error_exit(rc
, __func__
);
151 rc
= pthread_cond_init(&sem
->cond
, NULL
);
153 error_exit(rc
, __func__
);
156 error_exit(EINVAL
, __func__
);
160 rc
= sem_init(&sem
->sem
, 0, init
);
162 error_exit(errno
, __func__
);
167 void qemu_sem_destroy(QemuSemaphore
*sem
)
171 #if defined(__APPLE__) || defined(__NetBSD__)
172 rc
= pthread_cond_destroy(&sem
->cond
);
174 error_exit(rc
, __func__
);
176 rc
= pthread_mutex_destroy(&sem
->lock
);
178 error_exit(rc
, __func__
);
181 rc
= sem_destroy(&sem
->sem
);
183 error_exit(errno
, __func__
);
188 void qemu_sem_post(QemuSemaphore
*sem
)
192 #if defined(__APPLE__) || defined(__NetBSD__)
193 pthread_mutex_lock(&sem
->lock
);
194 if (sem
->count
== UINT_MAX
) {
198 rc
= pthread_cond_signal(&sem
->cond
);
200 pthread_mutex_unlock(&sem
->lock
);
202 error_exit(rc
, __func__
);
205 rc
= sem_post(&sem
->sem
);
207 error_exit(errno
, __func__
);
212 static void compute_abs_deadline(struct timespec
*ts
, int ms
)
215 gettimeofday(&tv
, NULL
);
216 ts
->tv_nsec
= tv
.tv_usec
* 1000 + (ms
% 1000) * 1000000;
217 ts
->tv_sec
= tv
.tv_sec
+ ms
/ 1000;
218 if (ts
->tv_nsec
>= 1000000000) {
220 ts
->tv_nsec
-= 1000000000;
224 int qemu_sem_timedwait(QemuSemaphore
*sem
, int ms
)
229 #if defined(__APPLE__) || defined(__NetBSD__)
231 compute_abs_deadline(&ts
, ms
);
232 pthread_mutex_lock(&sem
->lock
);
233 while (sem
->count
== 0) {
234 rc
= pthread_cond_timedwait(&sem
->cond
, &sem
->lock
, &ts
);
235 if (rc
== ETIMEDOUT
) {
239 error_exit(rc
, __func__
);
242 if (rc
!= ETIMEDOUT
) {
245 pthread_mutex_unlock(&sem
->lock
);
246 return (rc
== ETIMEDOUT
? -1 : 0);
249 /* This is cheaper than sem_timedwait. */
251 rc
= sem_trywait(&sem
->sem
);
252 } while (rc
== -1 && errno
== EINTR
);
253 if (rc
== -1 && errno
== EAGAIN
) {
257 compute_abs_deadline(&ts
, ms
);
259 rc
= sem_timedwait(&sem
->sem
, &ts
);
260 } while (rc
== -1 && errno
== EINTR
);
261 if (rc
== -1 && errno
== ETIMEDOUT
) {
266 error_exit(errno
, __func__
);
272 void qemu_sem_wait(QemuSemaphore
*sem
)
276 #if defined(__APPLE__) || defined(__NetBSD__)
277 pthread_mutex_lock(&sem
->lock
);
278 while (sem
->count
== 0) {
279 rc
= pthread_cond_wait(&sem
->cond
, &sem
->lock
);
281 error_exit(rc
, __func__
);
285 pthread_mutex_unlock(&sem
->lock
);
288 rc
= sem_wait(&sem
->sem
);
289 } while (rc
== -1 && errno
== EINTR
);
291 error_exit(errno
, __func__
);
297 #define futex(...) syscall(__NR_futex, __VA_ARGS__)
299 static inline void futex_wake(QemuEvent
*ev
, int n
)
301 futex(ev
, FUTEX_WAKE
, n
, NULL
, NULL
, 0);
304 static inline void futex_wait(QemuEvent
*ev
, unsigned val
)
306 while (futex(ev
, FUTEX_WAIT
, (int) val
, NULL
, NULL
, 0)) {
311 break; /* get out of switch and retry */
318 static inline void futex_wake(QemuEvent
*ev
, int n
)
320 pthread_mutex_lock(&ev
->lock
);
322 pthread_cond_signal(&ev
->cond
);
324 pthread_cond_broadcast(&ev
->cond
);
326 pthread_mutex_unlock(&ev
->lock
);
329 static inline void futex_wait(QemuEvent
*ev
, unsigned val
)
331 pthread_mutex_lock(&ev
->lock
);
332 if (ev
->value
== val
) {
333 pthread_cond_wait(&ev
->cond
, &ev
->lock
);
335 pthread_mutex_unlock(&ev
->lock
);
339 /* Valid transitions:
340 * - free->set, when setting the event
341 * - busy->set, when setting the event, followed by futex_wake
342 * - set->free, when resetting the event
343 * - free->busy, when waiting
345 * set->busy does not happen (it can be observed from the outside but
346 * it really is set->free->busy).
348 * busy->free provably cannot happen; to enforce it, the set->free transition
349 * is done with an OR, which becomes a no-op if the event has concurrently
350 * transitioned to free or busy.
357 void qemu_event_init(QemuEvent
*ev
, bool init
)
360 pthread_mutex_init(&ev
->lock
, NULL
);
361 pthread_cond_init(&ev
->cond
, NULL
);
364 ev
->value
= (init
? EV_SET
: EV_FREE
);
367 void qemu_event_destroy(QemuEvent
*ev
)
370 pthread_mutex_destroy(&ev
->lock
);
371 pthread_cond_destroy(&ev
->cond
);
375 void qemu_event_set(QemuEvent
*ev
)
377 /* qemu_event_set has release semantics, but because it *loads*
378 * ev->value we need a full memory barrier here.
381 if (atomic_read(&ev
->value
) != EV_SET
) {
382 if (atomic_xchg(&ev
->value
, EV_SET
) == EV_BUSY
) {
383 /* There were waiters, wake them up. */
384 futex_wake(ev
, INT_MAX
);
389 void qemu_event_reset(QemuEvent
*ev
)
393 value
= atomic_read(&ev
->value
);
395 if (value
== EV_SET
) {
397 * If there was a concurrent reset (or even reset+wait),
398 * do nothing. Otherwise change EV_SET->EV_FREE.
400 atomic_or(&ev
->value
, EV_FREE
);
404 void qemu_event_wait(QemuEvent
*ev
)
408 value
= atomic_read(&ev
->value
);
410 if (value
!= EV_SET
) {
411 if (value
== EV_FREE
) {
413 * Leave the event reset and tell qemu_event_set that there
414 * are waiters. No need to retry, because there cannot be
415 * a concurrent busy->free transition. After the CAS, the
416 * event will be either set or busy.
418 if (atomic_cmpxchg(&ev
->value
, EV_FREE
, EV_BUSY
) == EV_SET
) {
422 futex_wait(ev
, EV_BUSY
);
426 static pthread_key_t exit_key
;
428 union NotifierThreadData
{
432 QEMU_BUILD_BUG_ON(sizeof(union NotifierThreadData
) != sizeof(void *));
434 void qemu_thread_atexit_add(Notifier
*notifier
)
436 union NotifierThreadData ntd
;
437 ntd
.ptr
= pthread_getspecific(exit_key
);
438 notifier_list_add(&ntd
.list
, notifier
);
439 pthread_setspecific(exit_key
, ntd
.ptr
);
442 void qemu_thread_atexit_remove(Notifier
*notifier
)
444 union NotifierThreadData ntd
;
445 ntd
.ptr
= pthread_getspecific(exit_key
);
446 notifier_remove(notifier
);
447 pthread_setspecific(exit_key
, ntd
.ptr
);
450 static void qemu_thread_atexit_run(void *arg
)
452 union NotifierThreadData ntd
= { .ptr
= arg
};
453 notifier_list_notify(&ntd
.list
, NULL
);
456 static void __attribute__((constructor
)) qemu_thread_atexit_init(void)
458 pthread_key_create(&exit_key
, qemu_thread_atexit_run
);
462 /* Attempt to set the threads name; note that this is for debug, so
463 * we're not going to fail if we can't set it.
465 static void qemu_thread_set_name(QemuThread
*thread
, const char *name
)
467 #ifdef CONFIG_PTHREAD_SETNAME_NP
468 pthread_setname_np(thread
->thread
, name
);
472 void qemu_thread_create(QemuThread
*thread
, const char *name
,
473 void *(*start_routine
)(void*),
476 sigset_t set
, oldset
;
480 err
= pthread_attr_init(&attr
);
482 error_exit(err
, __func__
);
484 if (mode
== QEMU_THREAD_DETACHED
) {
485 err
= pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_DETACHED
);
487 error_exit(err
, __func__
);
491 /* Leave signal handling to the iothread. */
493 pthread_sigmask(SIG_SETMASK
, &set
, &oldset
);
494 err
= pthread_create(&thread
->thread
, &attr
, start_routine
, arg
);
496 error_exit(err
, __func__
);
499 qemu_thread_set_name(thread
, name
);
502 pthread_sigmask(SIG_SETMASK
, &oldset
, NULL
);
504 pthread_attr_destroy(&attr
);
507 void qemu_thread_get_self(QemuThread
*thread
)
509 thread
->thread
= pthread_self();
512 bool qemu_thread_is_self(QemuThread
*thread
)
514 return pthread_equal(pthread_self(), thread
->thread
);
517 void qemu_thread_exit(void *retval
)
519 pthread_exit(retval
);
522 void *qemu_thread_join(QemuThread
*thread
)
527 err
= pthread_join(thread
->thread
, &ret
);
529 error_exit(err
, __func__
);