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