1#include "qemu-common.h"
2#include "audio.h"
3
4#define AUDIO_CAP "audio-pt"
5
6#include "audio_int.h"
7#include "audio_pt_int.h"
8
9#include <signal.h>
10
11static void logerr (struct audio_pt *pt, int err, 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
23int 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, AUDIO_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, AUDIO_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, AUDIO_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, AUDIO_FUNC);
84    }
85
86 err0:
87    logerr (p, err, "%s(%s): %s failed", cap, AUDIO_FUNC, efunc);
88    return -1;
89}
90
91int 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, AUDIO_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, AUDIO_FUNC);
104        ret = -1;
105    }
106    return ret;
107}
108
109int 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, AUDIO_FUNC);
116        return -1;
117    }
118    return 0;
119}
120
121int 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, AUDIO_FUNC);
128        return -1;
129    }
130    return 0;
131}
132
133int 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, AUDIO_FUNC);
140        return -1;
141    }
142    return 0;
143}
144
145int 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, AUDIO_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, AUDIO_FUNC);
157        return -1;
158    }
159    return 0;
160}
161
162int 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, AUDIO_FUNC);
170        return -1;
171    }
172    *arg = ret;
173    return 0;
174}
175