blob: fd9d7140381af69db13625b6f7cd7d071bbd3942 [file] [log] [blame]
aliguorie5d355d2009-04-24 18:03:15 +00001/*
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 */
Peter Maydellaafd7582016-01-29 17:49:55 +000013#include "qemu/osdep.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010014#include "qemu/thread.h"
Paolo Bonzinic7c4d062013-09-25 14:20:59 +080015#include "qemu/atomic.h"
Paolo Bonzinief571372014-12-02 12:05:45 +010016#include "qemu/notify.h"
Peter Xuf1aff7a2018-04-25 10:54:57 +080017#include "qemu-thread-common.h"
Robert Foleyce9f0e52020-06-12 20:02:33 +010018#include "qemu/tsan.h"
aliguorie5d355d2009-04-24 18:03:15 +000019
Dr. David Alan Gilbert8f480de2014-01-30 10:20:31 +000020static bool name_threads;
21
22void qemu_thread_naming(bool enable)
23{
24 name_threads = enable;
Dr. David Alan Gilbert5c312072014-03-12 11:48:18 +000025
26#ifndef CONFIG_THREAD_SETNAME_BYTHREAD
27 /* This is a debugging option, not fatal */
28 if (enable) {
29 fprintf(stderr, "qemu: thread naming not supported on this host\n");
30 }
31#endif
Dr. David Alan Gilbert8f480de2014-01-30 10:20:31 +000032}
33
aliguorie5d355d2009-04-24 18:03:15 +000034static void error_exit(int err, const char *msg)
35{
36 fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
Jan Kiszka53380ac2011-09-21 09:28:31 +020037 abort();
aliguorie5d355d2009-04-24 18:03:15 +000038}
39
Yury Kotov3dcc9c62019-09-09 16:13:33 +030040static void compute_abs_deadline(struct timespec *ts, int ms)
41{
42 struct timeval tv;
43 gettimeofday(&tv, NULL);
44 ts->tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000;
45 ts->tv_sec = tv.tv_sec + ms / 1000;
46 if (ts->tv_nsec >= 1000000000) {
47 ts->tv_sec++;
48 ts->tv_nsec -= 1000000000;
49 }
50}
51
aliguorie5d355d2009-04-24 18:03:15 +000052void qemu_mutex_init(QemuMutex *mutex)
53{
54 int err;
55
Paolo Bonzini24fa9042015-03-05 16:47:14 +010056 err = pthread_mutex_init(&mutex->lock, NULL);
aliguorie5d355d2009-04-24 18:03:15 +000057 if (err)
58 error_exit(err, __func__);
Peter Xuf1aff7a2018-04-25 10:54:57 +080059 qemu_mutex_post_init(mutex);
aliguorie5d355d2009-04-24 18:03:15 +000060}
61
Corentin Chary313b1d62010-07-07 20:58:01 +020062void qemu_mutex_destroy(QemuMutex *mutex)
63{
64 int err;
65
Fam Zhengc0963582017-07-04 20:23:25 +080066 assert(mutex->initialized);
67 mutex->initialized = false;
Corentin Chary313b1d62010-07-07 20:58:01 +020068 err = pthread_mutex_destroy(&mutex->lock);
69 if (err)
70 error_exit(err, __func__);
71}
72
Alex Bennée6c27a0d2018-01-11 11:27:16 +030073void qemu_mutex_lock_impl(QemuMutex *mutex, const char *file, const int line)
aliguorie5d355d2009-04-24 18:03:15 +000074{
75 int err;
76
Fam Zhengc0963582017-07-04 20:23:25 +080077 assert(mutex->initialized);
Peter Xuf1aff7a2018-04-25 10:54:57 +080078 qemu_mutex_pre_lock(mutex, file, line);
aliguorie5d355d2009-04-24 18:03:15 +000079 err = pthread_mutex_lock(&mutex->lock);
80 if (err)
81 error_exit(err, __func__);
Peter Xuf1aff7a2018-04-25 10:54:57 +080082 qemu_mutex_post_lock(mutex, file, line);
aliguorie5d355d2009-04-24 18:03:15 +000083}
84
Alex Bennée6c27a0d2018-01-11 11:27:16 +030085int qemu_mutex_trylock_impl(QemuMutex *mutex, const char *file, const int line)
aliguorie5d355d2009-04-24 18:03:15 +000086{
Jose Ricardo Ziviani31f5a722017-04-24 14:19:58 -030087 int err;
88
Fam Zhengc0963582017-07-04 20:23:25 +080089 assert(mutex->initialized);
Jose Ricardo Ziviani31f5a722017-04-24 14:19:58 -030090 err = pthread_mutex_trylock(&mutex->lock);
91 if (err == 0) {
Peter Xuf1aff7a2018-04-25 10:54:57 +080092 qemu_mutex_post_lock(mutex, file, line);
Jose Ricardo Ziviani31f5a722017-04-24 14:19:58 -030093 return 0;
94 }
95 if (err != EBUSY) {
96 error_exit(err, __func__);
97 }
98 return -EBUSY;
aliguorie5d355d2009-04-24 18:03:15 +000099}
100
Alex Bennée6c27a0d2018-01-11 11:27:16 +0300101void qemu_mutex_unlock_impl(QemuMutex *mutex, const char *file, const int line)
aliguorie5d355d2009-04-24 18:03:15 +0000102{
103 int err;
104
Fam Zhengc0963582017-07-04 20:23:25 +0800105 assert(mutex->initialized);
Peter Xuf1aff7a2018-04-25 10:54:57 +0800106 qemu_mutex_pre_unlock(mutex, file, line);
aliguorie5d355d2009-04-24 18:03:15 +0000107 err = pthread_mutex_unlock(&mutex->lock);
108 if (err)
109 error_exit(err, __func__);
110}
111
Paolo Bonzinifeadec62016-10-27 12:49:07 +0200112void qemu_rec_mutex_init(QemuRecMutex *mutex)
113{
114 int err;
115 pthread_mutexattr_t attr;
116
117 pthread_mutexattr_init(&attr);
118 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
Richard Henderson6c986352021-06-14 16:31:40 -0700119 err = pthread_mutex_init(&mutex->m.lock, &attr);
Paolo Bonzinifeadec62016-10-27 12:49:07 +0200120 pthread_mutexattr_destroy(&attr);
121 if (err) {
122 error_exit(err, __func__);
123 }
Richard Henderson6c986352021-06-14 16:31:40 -0700124 mutex->m.initialized = true;
Paolo Bonzinifeadec62016-10-27 12:49:07 +0200125}
126
Richard Henderson4b193bb2021-06-14 16:31:38 -0700127void qemu_rec_mutex_destroy(QemuRecMutex *mutex)
128{
Richard Henderson6c986352021-06-14 16:31:40 -0700129 qemu_mutex_destroy(&mutex->m);
Richard Henderson4b193bb2021-06-14 16:31:38 -0700130}
131
132void qemu_rec_mutex_lock_impl(QemuRecMutex *mutex, const char *file, int line)
133{
Richard Henderson6c986352021-06-14 16:31:40 -0700134 qemu_mutex_lock_impl(&mutex->m, file, line);
Richard Henderson4b193bb2021-06-14 16:31:38 -0700135}
136
137int qemu_rec_mutex_trylock_impl(QemuRecMutex *mutex, const char *file, int line)
138{
Richard Henderson6c986352021-06-14 16:31:40 -0700139 return qemu_mutex_trylock_impl(&mutex->m, file, line);
Richard Henderson4b193bb2021-06-14 16:31:38 -0700140}
141
Richard Henderson9c75bae2021-06-14 16:31:39 -0700142void qemu_rec_mutex_unlock_impl(QemuRecMutex *mutex, const char *file, int line)
Richard Henderson4b193bb2021-06-14 16:31:38 -0700143{
Richard Henderson6c986352021-06-14 16:31:40 -0700144 qemu_mutex_unlock_impl(&mutex->m, file, line);
Richard Henderson4b193bb2021-06-14 16:31:38 -0700145}
146
aliguorie5d355d2009-04-24 18:03:15 +0000147void qemu_cond_init(QemuCond *cond)
148{
149 int err;
150
151 err = pthread_cond_init(&cond->cond, NULL);
152 if (err)
153 error_exit(err, __func__);
Fam Zhengc0963582017-07-04 20:23:25 +0800154 cond->initialized = true;
aliguorie5d355d2009-04-24 18:03:15 +0000155}
156
Corentin Chary313b1d62010-07-07 20:58:01 +0200157void qemu_cond_destroy(QemuCond *cond)
158{
159 int err;
160
Fam Zhengc0963582017-07-04 20:23:25 +0800161 assert(cond->initialized);
162 cond->initialized = false;
Corentin Chary313b1d62010-07-07 20:58:01 +0200163 err = pthread_cond_destroy(&cond->cond);
164 if (err)
165 error_exit(err, __func__);
166}
167
aliguorie5d355d2009-04-24 18:03:15 +0000168void qemu_cond_signal(QemuCond *cond)
169{
170 int err;
171
Fam Zhengc0963582017-07-04 20:23:25 +0800172 assert(cond->initialized);
aliguorie5d355d2009-04-24 18:03:15 +0000173 err = pthread_cond_signal(&cond->cond);
174 if (err)
175 error_exit(err, __func__);
176}
177
178void qemu_cond_broadcast(QemuCond *cond)
179{
180 int err;
181
Fam Zhengc0963582017-07-04 20:23:25 +0800182 assert(cond->initialized);
aliguorie5d355d2009-04-24 18:03:15 +0000183 err = pthread_cond_broadcast(&cond->cond);
184 if (err)
185 error_exit(err, __func__);
186}
187
Alex Bennée6c27a0d2018-01-11 11:27:16 +0300188void qemu_cond_wait_impl(QemuCond *cond, QemuMutex *mutex, const char *file, const int line)
aliguorie5d355d2009-04-24 18:03:15 +0000189{
190 int err;
191
Fam Zhengc0963582017-07-04 20:23:25 +0800192 assert(cond->initialized);
Peter Xuf1aff7a2018-04-25 10:54:57 +0800193 qemu_mutex_pre_unlock(mutex, file, line);
aliguorie5d355d2009-04-24 18:03:15 +0000194 err = pthread_cond_wait(&cond->cond, &mutex->lock);
Peter Xuf1aff7a2018-04-25 10:54:57 +0800195 qemu_mutex_post_lock(mutex, file, line);
aliguorie5d355d2009-04-24 18:03:15 +0000196 if (err)
197 error_exit(err, __func__);
198}
199
Yury Kotov3dcc9c62019-09-09 16:13:33 +0300200bool qemu_cond_timedwait_impl(QemuCond *cond, QemuMutex *mutex, int ms,
201 const char *file, const int line)
202{
203 int err;
204 struct timespec ts;
205
206 assert(cond->initialized);
207 trace_qemu_mutex_unlock(mutex, file, line);
208 compute_abs_deadline(&ts, ms);
209 err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);
210 trace_qemu_mutex_locked(mutex, file, line);
211 if (err && err != ETIMEDOUT) {
212 error_exit(err, __func__);
213 }
214 return err != ETIMEDOUT;
215}
216
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200217void qemu_sem_init(QemuSemaphore *sem, int init)
218{
219 int rc;
220
Peter Maydell401bc052017-09-05 13:19:32 +0100221#ifndef CONFIG_SEM_TIMEDWAIT
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100222 rc = pthread_mutex_init(&sem->lock, NULL);
223 if (rc != 0) {
224 error_exit(rc, __func__);
225 }
226 rc = pthread_cond_init(&sem->cond, NULL);
227 if (rc != 0) {
228 error_exit(rc, __func__);
229 }
230 if (init < 0) {
231 error_exit(EINVAL, __func__);
232 }
233 sem->count = init;
234#else
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200235 rc = sem_init(&sem->sem, 0, init);
236 if (rc < 0) {
237 error_exit(errno, __func__);
238 }
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100239#endif
Fam Zhengc0963582017-07-04 20:23:25 +0800240 sem->initialized = true;
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200241}
242
243void qemu_sem_destroy(QemuSemaphore *sem)
244{
245 int rc;
246
Fam Zhengc0963582017-07-04 20:23:25 +0800247 assert(sem->initialized);
248 sem->initialized = false;
Peter Maydell401bc052017-09-05 13:19:32 +0100249#ifndef CONFIG_SEM_TIMEDWAIT
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100250 rc = pthread_cond_destroy(&sem->cond);
251 if (rc < 0) {
252 error_exit(rc, __func__);
253 }
254 rc = pthread_mutex_destroy(&sem->lock);
255 if (rc < 0) {
256 error_exit(rc, __func__);
257 }
258#else
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200259 rc = sem_destroy(&sem->sem);
260 if (rc < 0) {
261 error_exit(errno, __func__);
262 }
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100263#endif
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200264}
265
266void qemu_sem_post(QemuSemaphore *sem)
267{
268 int rc;
269
Fam Zhengc0963582017-07-04 20:23:25 +0800270 assert(sem->initialized);
Peter Maydell401bc052017-09-05 13:19:32 +0100271#ifndef CONFIG_SEM_TIMEDWAIT
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100272 pthread_mutex_lock(&sem->lock);
Izumi Tsutsui79761c62013-07-03 17:58:14 +0900273 if (sem->count == UINT_MAX) {
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100274 rc = EINVAL;
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100275 } else {
Izumi Tsutsui79761c62013-07-03 17:58:14 +0900276 sem->count++;
277 rc = pthread_cond_signal(&sem->cond);
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100278 }
279 pthread_mutex_unlock(&sem->lock);
280 if (rc != 0) {
281 error_exit(rc, __func__);
282 }
283#else
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200284 rc = sem_post(&sem->sem);
285 if (rc < 0) {
286 error_exit(errno, __func__);
287 }
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100288#endif
289}
290
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200291int qemu_sem_timedwait(QemuSemaphore *sem, int ms)
292{
293 int rc;
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100294 struct timespec ts;
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200295
Fam Zhengc0963582017-07-04 20:23:25 +0800296 assert(sem->initialized);
Peter Maydell401bc052017-09-05 13:19:32 +0100297#ifndef CONFIG_SEM_TIMEDWAIT
Izumi Tsutsui79761c62013-07-03 17:58:14 +0900298 rc = 0;
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100299 compute_abs_deadline(&ts, ms);
300 pthread_mutex_lock(&sem->lock);
Izumi Tsutsui79761c62013-07-03 17:58:14 +0900301 while (sem->count == 0) {
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100302 rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts);
303 if (rc == ETIMEDOUT) {
304 break;
305 }
306 if (rc != 0) {
307 error_exit(rc, __func__);
308 }
309 }
Izumi Tsutsui79761c62013-07-03 17:58:14 +0900310 if (rc != ETIMEDOUT) {
311 --sem->count;
312 }
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100313 pthread_mutex_unlock(&sem->lock);
314 return (rc == ETIMEDOUT ? -1 : 0);
315#else
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200316 if (ms <= 0) {
317 /* This is cheaper than sem_timedwait. */
318 do {
319 rc = sem_trywait(&sem->sem);
320 } while (rc == -1 && errno == EINTR);
321 if (rc == -1 && errno == EAGAIN) {
322 return -1;
323 }
324 } else {
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100325 compute_abs_deadline(&ts, ms);
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200326 do {
327 rc = sem_timedwait(&sem->sem, &ts);
328 } while (rc == -1 && errno == EINTR);
329 if (rc == -1 && errno == ETIMEDOUT) {
330 return -1;
331 }
332 }
333 if (rc < 0) {
334 error_exit(errno, __func__);
335 }
336 return 0;
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100337#endif
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200338}
339
340void qemu_sem_wait(QemuSemaphore *sem)
341{
342 int rc;
343
Fam Zhengc0963582017-07-04 20:23:25 +0800344 assert(sem->initialized);
Peter Maydell401bc052017-09-05 13:19:32 +0100345#ifndef CONFIG_SEM_TIMEDWAIT
Izumi Tsutsui79761c62013-07-03 17:58:14 +0900346 pthread_mutex_lock(&sem->lock);
347 while (sem->count == 0) {
348 rc = pthread_cond_wait(&sem->cond, &sem->lock);
349 if (rc != 0) {
350 error_exit(rc, __func__);
351 }
352 }
353 --sem->count;
354 pthread_mutex_unlock(&sem->lock);
355#else
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200356 do {
357 rc = sem_wait(&sem->sem);
358 } while (rc == -1 && errno == EINTR);
359 if (rc < 0) {
360 error_exit(errno, __func__);
361 }
Paolo Bonzinic166cb72012-11-02 15:43:21 +0100362#endif
Paolo Bonzini38b14db2011-08-08 14:36:41 +0200363}
364
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800365#ifdef __linux__
Paolo Bonzinifbcc3e52017-01-12 19:07:54 +0100366#include "qemu/futex.h"
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800367#else
Paolo Bonzinifbcc3e52017-01-12 19:07:54 +0100368static inline void qemu_futex_wake(QemuEvent *ev, int n)
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800369{
Fam Zhengc0963582017-07-04 20:23:25 +0800370 assert(ev->initialized);
Paolo Bonzini158ef8c2015-02-02 16:36:51 +0100371 pthread_mutex_lock(&ev->lock);
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800372 if (n == 1) {
373 pthread_cond_signal(&ev->cond);
374 } else {
375 pthread_cond_broadcast(&ev->cond);
376 }
Paolo Bonzini158ef8c2015-02-02 16:36:51 +0100377 pthread_mutex_unlock(&ev->lock);
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800378}
379
Paolo Bonzinifbcc3e52017-01-12 19:07:54 +0100380static inline void qemu_futex_wait(QemuEvent *ev, unsigned val)
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800381{
Fam Zhengc0963582017-07-04 20:23:25 +0800382 assert(ev->initialized);
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800383 pthread_mutex_lock(&ev->lock);
384 if (ev->value == val) {
385 pthread_cond_wait(&ev->cond, &ev->lock);
386 }
387 pthread_mutex_unlock(&ev->lock);
388}
389#endif
390
391/* Valid transitions:
392 * - free->set, when setting the event
Paolo Bonzinifbcc3e52017-01-12 19:07:54 +0100393 * - busy->set, when setting the event, followed by qemu_futex_wake
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800394 * - set->free, when resetting the event
395 * - free->busy, when waiting
396 *
397 * set->busy does not happen (it can be observed from the outside but
398 * it really is set->free->busy).
399 *
400 * busy->free provably cannot happen; to enforce it, the set->free transition
401 * is done with an OR, which becomes a no-op if the event has concurrently
402 * transitioned to free or busy.
403 */
404
405#define EV_SET 0
406#define EV_FREE 1
407#define EV_BUSY -1
408
409void qemu_event_init(QemuEvent *ev, bool init)
410{
411#ifndef __linux__
412 pthread_mutex_init(&ev->lock, NULL);
413 pthread_cond_init(&ev->cond, NULL);
414#endif
415
416 ev->value = (init ? EV_SET : EV_FREE);
Fam Zhengc0963582017-07-04 20:23:25 +0800417 ev->initialized = true;
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800418}
419
420void qemu_event_destroy(QemuEvent *ev)
421{
Fam Zhengc0963582017-07-04 20:23:25 +0800422 assert(ev->initialized);
423 ev->initialized = false;
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800424#ifndef __linux__
425 pthread_mutex_destroy(&ev->lock);
426 pthread_cond_destroy(&ev->cond);
427#endif
428}
429
430void qemu_event_set(QemuEvent *ev)
431{
Paolo Bonzini374293c2016-09-19 11:10:57 +0200432 /* qemu_event_set has release semantics, but because it *loads*
433 * ev->value we need a full memory barrier here.
434 */
Fam Zhengc0963582017-07-04 20:23:25 +0800435 assert(ev->initialized);
Paolo Bonzini374293c2016-09-19 11:10:57 +0200436 smp_mb();
Stefan Hajnoczid73415a2020-09-23 11:56:46 +0100437 if (qatomic_read(&ev->value) != EV_SET) {
438 if (qatomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800439 /* There were waiters, wake them up. */
Paolo Bonzinifbcc3e52017-01-12 19:07:54 +0100440 qemu_futex_wake(ev, INT_MAX);
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800441 }
442 }
443}
444
445void qemu_event_reset(QemuEvent *ev)
446{
Paolo Bonzini374293c2016-09-19 11:10:57 +0200447 unsigned value;
448
Fam Zhengc0963582017-07-04 20:23:25 +0800449 assert(ev->initialized);
Stefan Hajnoczid73415a2020-09-23 11:56:46 +0100450 value = qatomic_read(&ev->value);
Paolo Bonzini374293c2016-09-19 11:10:57 +0200451 smp_mb_acquire();
452 if (value == EV_SET) {
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800453 /*
454 * If there was a concurrent reset (or even reset+wait),
455 * do nothing. Otherwise change EV_SET->EV_FREE.
456 */
Stefan Hajnoczid73415a2020-09-23 11:56:46 +0100457 qatomic_or(&ev->value, EV_FREE);
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800458 }
459}
460
461void qemu_event_wait(QemuEvent *ev)
462{
463 unsigned value;
464
Fam Zhengc0963582017-07-04 20:23:25 +0800465 assert(ev->initialized);
Stefan Hajnoczid73415a2020-09-23 11:56:46 +0100466 value = qatomic_read(&ev->value);
Paolo Bonzini374293c2016-09-19 11:10:57 +0200467 smp_mb_acquire();
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800468 if (value != EV_SET) {
469 if (value == EV_FREE) {
470 /*
471 * Leave the event reset and tell qemu_event_set that there
472 * are waiters. No need to retry, because there cannot be
Veres Lajos67cc32e2015-09-08 22:45:14 +0100473 * a concurrent busy->free transition. After the CAS, the
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800474 * event will be either set or busy.
475 */
Stefan Hajnoczid73415a2020-09-23 11:56:46 +0100476 if (qatomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) {
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800477 return;
478 }
479 }
Paolo Bonzinifbcc3e52017-01-12 19:07:54 +0100480 qemu_futex_wait(ev, EV_BUSY);
Paolo Bonzinic7c4d062013-09-25 14:20:59 +0800481 }
482}
483
Peter Maydella4587742018-11-05 13:55:38 +0000484static __thread NotifierList thread_exit;
Paolo Bonzinief571372014-12-02 12:05:45 +0100485
Peter Maydella4587742018-11-05 13:55:38 +0000486/*
487 * Note that in this implementation you can register a thread-exit
488 * notifier for the main thread, but it will never be called.
489 * This is OK because main thread exit can only happen when the
490 * entire process is exiting, and the API allows notifiers to not
491 * be called on process exit.
492 */
Paolo Bonzinief571372014-12-02 12:05:45 +0100493void qemu_thread_atexit_add(Notifier *notifier)
494{
Peter Maydella4587742018-11-05 13:55:38 +0000495 notifier_list_add(&thread_exit, notifier);
Paolo Bonzinief571372014-12-02 12:05:45 +0100496}
497
498void qemu_thread_atexit_remove(Notifier *notifier)
499{
Paolo Bonzinief571372014-12-02 12:05:45 +0100500 notifier_remove(notifier);
Paolo Bonzinief571372014-12-02 12:05:45 +0100501}
502
Peter Maydella4587742018-11-05 13:55:38 +0000503static void qemu_thread_atexit_notify(void *arg)
Paolo Bonzinief571372014-12-02 12:05:45 +0100504{
Peter Maydella4587742018-11-05 13:55:38 +0000505 /*
506 * Called when non-main thread exits (via qemu_thread_exit()
507 * or by returning from its start routine.)
508 */
509 notifier_list_notify(&thread_exit, NULL);
Paolo Bonzinief571372014-12-02 12:05:45 +0100510}
511
linzhecheng68a93982017-11-28 12:46:56 +0800512typedef struct {
513 void *(*start_routine)(void *);
514 void *arg;
515 char *name;
516} QemuThreadArgs;
517
518static void *qemu_thread_start(void *args)
519{
520 QemuThreadArgs *qemu_thread_args = args;
521 void *(*start_routine)(void *) = qemu_thread_args->start_routine;
522 void *arg = qemu_thread_args->arg;
Peter Maydella4587742018-11-05 13:55:38 +0000523 void *r;
linzhecheng68a93982017-11-28 12:46:56 +0800524
Roman Bolshakov479a5742018-12-17 23:26:01 +0300525#ifdef CONFIG_THREAD_SETNAME_BYTHREAD
linzhecheng68a93982017-11-28 12:46:56 +0800526 /* 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 */
Peter Xud820fa52018-04-12 13:34:44 +0800529 if (name_threads && qemu_thread_args->name) {
Roman Bolshakov479a5742018-12-17 23:26:01 +0300530# if defined(CONFIG_PTHREAD_SETNAME_NP_W_TID)
Peter Xud820fa52018-04-12 13:34:44 +0800531 pthread_setname_np(pthread_self(), qemu_thread_args->name);
Roman Bolshakov479a5742018-12-17 23:26:01 +0300532# elif defined(CONFIG_PTHREAD_SETNAME_NP_WO_TID)
533 pthread_setname_np(qemu_thread_args->name);
534# endif
Peter Xud820fa52018-04-12 13:34:44 +0800535 }
536#endif
Robert Foleyce9f0e52020-06-12 20:02:33 +0100537 QEMU_TSAN_ANNOTATE_THREAD_NAME(qemu_thread_args->name);
linzhecheng68a93982017-11-28 12:46:56 +0800538 g_free(qemu_thread_args->name);
539 g_free(qemu_thread_args);
Peter Maydella4587742018-11-05 13:55:38 +0000540 pthread_cleanup_push(qemu_thread_atexit_notify, NULL);
541 r = start_routine(arg);
542 pthread_cleanup_pop(1);
543 return r;
Dr. David Alan Gilbert5c312072014-03-12 11:48:18 +0000544}
545
Dr. David Alan Gilbert49001162014-01-30 10:20:32 +0000546void qemu_thread_create(QemuThread *thread, const char *name,
aliguorie5d355d2009-04-24 18:03:15 +0000547 void *(*start_routine)(void*),
Jan Kiszkacf218712011-12-12 17:21:31 +0100548 void *arg, int mode)
aliguorie5d355d2009-04-24 18:03:15 +0000549{
Jan Kiszkacf218712011-12-12 17:21:31 +0100550 sigset_t set, oldset;
aliguorie5d355d2009-04-24 18:03:15 +0000551 int err;
Jan Kiszka87630462011-12-12 17:21:32 +0100552 pthread_attr_t attr;
Peter Xud820fa52018-04-12 13:34:44 +0800553 QemuThreadArgs *qemu_thread_args;
aliguorie5d355d2009-04-24 18:03:15 +0000554
Jan Kiszka87630462011-12-12 17:21:32 +0100555 err = pthread_attr_init(&attr);
556 if (err) {
557 error_exit(err, __func__);
558 }
Paolo Bonzini55541c82010-06-03 15:20:32 +0200559
linzhecheng68a93982017-11-28 12:46:56 +0800560 if (mode == QEMU_THREAD_DETACHED) {
561 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
562 }
563
Jan Kiszkacf218712011-12-12 17:21:31 +0100564 /* Leave signal handling to the iothread. */
Paolo Bonzini55541c82010-06-03 15:20:32 +0200565 sigfillset(&set);
Roman Bolshakov21a43af2018-12-17 23:26:02 +0300566 /* Blocking the signals can result in undefined behaviour. */
567 sigdelset(&set, SIGSEGV);
568 sigdelset(&set, SIGFPE);
569 sigdelset(&set, SIGILL);
570 /* TODO avoid SIGBUS loss on macOS */
Paolo Bonzini55541c82010-06-03 15:20:32 +0200571 pthread_sigmask(SIG_SETMASK, &set, &oldset);
linzhecheng68a93982017-11-28 12:46:56 +0800572
Peter Xud820fa52018-04-12 13:34:44 +0800573 qemu_thread_args = g_new0(QemuThreadArgs, 1);
574 qemu_thread_args->name = g_strdup(name);
575 qemu_thread_args->start_routine = start_routine;
576 qemu_thread_args->arg = arg;
linzhecheng68a93982017-11-28 12:46:56 +0800577
Peter Xud820fa52018-04-12 13:34:44 +0800578 err = pthread_create(&thread->thread, &attr,
579 qemu_thread_start, qemu_thread_args);
linzhecheng68a93982017-11-28 12:46:56 +0800580
aliguorie5d355d2009-04-24 18:03:15 +0000581 if (err)
582 error_exit(err, __func__);
Paolo Bonzini55541c82010-06-03 15:20:32 +0200583
584 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
Jan Kiszka87630462011-12-12 17:21:32 +0100585
586 pthread_attr_destroy(&attr);
aliguorie5d355d2009-04-24 18:03:15 +0000587}
588
Jan Kiszkab7680cb2011-03-12 17:43:51 +0100589void qemu_thread_get_self(QemuThread *thread)
aliguorie5d355d2009-04-24 18:03:15 +0000590{
591 thread->thread = pthread_self();
592}
593
Andreas Färber2d797b62012-05-02 17:21:31 +0200594bool qemu_thread_is_self(QemuThread *thread)
aliguorie5d355d2009-04-24 18:03:15 +0000595{
Jan Kiszkab7680cb2011-03-12 17:43:51 +0100596 return pthread_equal(pthread_self(), thread->thread);
aliguorie5d355d2009-04-24 18:03:15 +0000597}
598
Corentin Chary313b1d62010-07-07 20:58:01 +0200599void qemu_thread_exit(void *retval)
600{
601 pthread_exit(retval);
602}
Jan Kiszka87630462011-12-12 17:21:32 +0100603
604void *qemu_thread_join(QemuThread *thread)
605{
606 int err;
607 void *ret;
608
609 err = pthread_join(thread->thread, &ret);
610 if (err) {
611 error_exit(err, __func__);
612 }
613 return ret;
614}