1 #include "qemu/osdep.h"
2 #include "qemu-common.h"
3 #include "audio.h"
4 
5 #define AUDIO_CAP "audio-pt"
6 
7 #include "audio_int.h"
8 #include "audio_pt_int.h"
9 
logerr(struct audio_pt * pt,int err,const char * fmt,...)10 static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err,
11                                        const char *fmt, ...)
12 {
13     va_list ap;
14 
15     va_start (ap, fmt);
16     AUD_vlog (pt->drv, fmt, ap);
17     va_end (ap);
18 
19     AUD_log (NULL, "\n");
20     AUD_log (pt->drv, "Reason: %s\n", strerror (err));
21 }
22 
audio_pt_init(struct audio_pt * p,void * (* func)(void *),void * opaque,const char * drv,const char * cap)23 int audio_pt_init (struct audio_pt *p, void *(*func) (void *),
24                    void *opaque, const char *drv, const char *cap)
25 {
26     int err, err2;
27     const char *efunc;
28     sigset_t set, old_set;
29 
30     p->drv = drv;
31 
32     err = sigfillset (&set);
33     if (err) {
34         logerr(p, errno, "%s(%s): sigfillset failed", cap, __func__);
35         return -1;
36     }
37 
38     err = pthread_mutex_init (&p->mutex, NULL);
39     if (err) {
40         efunc = "pthread_mutex_init";
41         goto err0;
42     }
43 
44     err = pthread_cond_init (&p->cond, NULL);
45     if (err) {
46         efunc = "pthread_cond_init";
47         goto err1;
48     }
49 
50     err = pthread_sigmask (SIG_BLOCK, &set, &old_set);
51     if (err) {
52         efunc = "pthread_sigmask";
53         goto err2;
54     }
55 
56     err = pthread_create (&p->thread, NULL, func, opaque);
57 
58     err2 = pthread_sigmask (SIG_SETMASK, &old_set, NULL);
59     if (err2) {
60         logerr(p, err2, "%s(%s): pthread_sigmask (restore) failed",
61                cap, __func__);
62         /* We have failed to restore original signal mask, all bets are off,
63            so terminate the process */
64         exit (EXIT_FAILURE);
65     }
66 
67     if (err) {
68         efunc = "pthread_create";
69         goto err2;
70     }
71 
72     return 0;
73 
74  err2:
75     err2 = pthread_cond_destroy (&p->cond);
76     if (err2) {
77         logerr(p, err2, "%s(%s): pthread_cond_destroy failed", cap, __func__);
78     }
79 
80  err1:
81     err2 = pthread_mutex_destroy (&p->mutex);
82     if (err2) {
83         logerr(p, err2, "%s(%s): pthread_mutex_destroy failed", cap, __func__);
84     }
85 
86  err0:
87     logerr(p, err, "%s(%s): %s failed", cap, __func__, efunc);
88     return -1;
89 }
90 
audio_pt_fini(struct audio_pt * p,const char * cap)91 int audio_pt_fini (struct audio_pt *p, const char *cap)
92 {
93     int err, ret = 0;
94 
95     err = pthread_cond_destroy (&p->cond);
96     if (err) {
97         logerr(p, err, "%s(%s): pthread_cond_destroy failed", cap, __func__);
98         ret = -1;
99     }
100 
101     err = pthread_mutex_destroy (&p->mutex);
102     if (err) {
103         logerr(p, err, "%s(%s): pthread_mutex_destroy failed", cap, __func__);
104         ret = -1;
105     }
106     return ret;
107 }
108 
audio_pt_lock(struct audio_pt * p,const char * cap)109 int audio_pt_lock (struct audio_pt *p, const char *cap)
110 {
111     int err;
112 
113     err = pthread_mutex_lock (&p->mutex);
114     if (err) {
115         logerr(p, err, "%s(%s): pthread_mutex_lock failed", cap, __func__);
116         return -1;
117     }
118     return 0;
119 }
120 
audio_pt_unlock(struct audio_pt * p,const char * cap)121 int audio_pt_unlock (struct audio_pt *p, const char *cap)
122 {
123     int err;
124 
125     err = pthread_mutex_unlock (&p->mutex);
126     if (err) {
127         logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__);
128         return -1;
129     }
130     return 0;
131 }
132 
audio_pt_wait(struct audio_pt * p,const char * cap)133 int audio_pt_wait (struct audio_pt *p, const char *cap)
134 {
135     int err;
136 
137     err = pthread_cond_wait (&p->cond, &p->mutex);
138     if (err) {
139         logerr(p, err, "%s(%s): pthread_cond_wait failed", cap, __func__);
140         return -1;
141     }
142     return 0;
143 }
144 
audio_pt_unlock_and_signal(struct audio_pt * p,const char * cap)145 int audio_pt_unlock_and_signal (struct audio_pt *p, const char *cap)
146 {
147     int err;
148 
149     err = pthread_mutex_unlock (&p->mutex);
150     if (err) {
151         logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__);
152         return -1;
153     }
154     err = pthread_cond_signal (&p->cond);
155     if (err) {
156         logerr(p, err, "%s(%s): pthread_cond_signal failed", cap, __func__);
157         return -1;
158     }
159     return 0;
160 }
161 
audio_pt_join(struct audio_pt * p,void ** arg,const char * cap)162 int audio_pt_join (struct audio_pt *p, void **arg, const char *cap)
163 {
164     int err;
165     void *ret;
166 
167     err = pthread_join (p->thread, &ret);
168     if (err) {
169         logerr(p, err, "%s(%s): pthread_join failed", cap, __func__);
170         return -1;
171     }
172     *arg = ret;
173     return 0;
174 }
175