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