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