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 <stdlib.h>
14 #include <stdio.h>
15 #include <errno.h>
16 #include <time.h>
17 #include <signal.h>
18 #include "unicorn/platform.h"
19 #include <string.h>
20 #include <limits.h>
21 #ifdef __linux__
22 #include <sys/syscall.h>
23 #include <linux/futex.h>
24 #endif
25 #include "qemu/thread.h"
26 #include "qemu/atomic.h"
27 
error_exit(int err,const char * msg)28 static void error_exit(int err, const char *msg)
29 {
30     fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err));
31     abort();
32 }
33 
qemu_thread_create(struct uc_struct * uc,QemuThread * thread,const char * name,void * (* start_routine)(void *),void * arg,int mode)34 int qemu_thread_create(struct uc_struct *uc, QemuThread *thread, const char *name,
35                        void *(*start_routine)(void*),
36                        void *arg, int mode)
37 {
38     sigset_t set, oldset;
39     int err;
40     pthread_attr_t attr;
41 
42     err = pthread_attr_init(&attr);
43     if (err) {
44         error_exit(err, __func__);
45         return -1;
46     }
47     if (mode == QEMU_THREAD_DETACHED) {
48         err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
49         if (err) {
50             error_exit(err, __func__);
51             return -1;
52         }
53     }
54 
55     /* Leave signal handling to the iothread.  */
56     sigfillset(&set);
57     pthread_sigmask(SIG_SETMASK, &set, &oldset);
58     err = pthread_create(&thread->thread, &attr, start_routine, arg);
59     if (err) {
60         error_exit(err, __func__);
61         return -1;
62     }
63 
64     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
65 
66     pthread_attr_destroy(&attr);
67 
68     return 0;
69 }
70 
qemu_thread_exit(struct uc_struct * uc,void * retval)71 void qemu_thread_exit(struct uc_struct *uc, void *retval)
72 {
73     pthread_exit(retval);
74 }
75 
qemu_thread_join(QemuThread * thread)76 void *qemu_thread_join(QemuThread *thread)
77 {
78     int err;
79     void *ret;
80 
81     err = pthread_join(thread->thread, &ret);
82     if (err) {
83         error_exit(err, __func__);
84     }
85     return ret;
86 }
87