sink-input: adjust log level of empty-pop operations
[platform/upstream/pulseaudio.git] / src / pulsecore / mutex-posix.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2006 Lennart Poettering
5
6   PulseAudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published
8   by the Free Software Foundation; either version 2.1 of the License,
9   or (at your option) any later version.
10
11   PulseAudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <pthread.h>
25 #include <errno.h>
26 #ifdef __TIZEN__
27 #include <sys/time.h>
28 #endif
29
30 #include <pulse/xmalloc.h>
31
32 #include <pulsecore/core-error.h>
33 #include <pulsecore/macro.h>
34
35 #include "mutex.h"
36
37 #ifdef __TIZEN__
38 struct pa_mutex {
39     unsigned int lock;
40     pthread_mutex_t mutex;
41     unsigned int unlock;
42 };
43 #else
44 struct pa_mutex {
45     pthread_mutex_t mutex;
46 };
47 #endif
48
49 struct pa_cond {
50     pthread_cond_t cond;
51 };
52
53 pa_mutex* pa_mutex_new(bool recursive, bool inherit_priority) {
54     pa_mutex *m;
55     pthread_mutexattr_t attr;
56 #ifdef HAVE_PTHREAD_PRIO_INHERIT
57     int r;
58 #endif
59
60     pa_assert_se(pthread_mutexattr_init(&attr) == 0);
61
62     if (recursive)
63         pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
64
65 #ifdef HAVE_PTHREAD_PRIO_INHERIT
66     if (inherit_priority) {
67         r = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
68         pa_assert(r == 0 || r == ENOTSUP);
69     }
70 #endif
71
72     m = pa_xnew(pa_mutex, 1);
73
74 #ifndef HAVE_PTHREAD_PRIO_INHERIT
75     pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
76
77 #else
78     if ((r = pthread_mutex_init(&m->mutex, &attr))) {
79
80         /* If this failed, then this was probably due to non-available
81          * priority inheritance. In which case we fall back to normal
82          * mutexes. */
83         pa_assert(r == ENOTSUP && inherit_priority);
84
85         pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_NONE) == 0);
86         pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
87     }
88 #endif
89
90 #ifdef __TIZEN__
91     m->lock = 0;
92     m->unlock = 0;
93 #endif
94
95     return m;
96 }
97
98 void pa_mutex_free(pa_mutex *m) {
99 #ifdef __TIZEN__
100     int ret;
101 #endif
102     pa_assert(m);
103
104 #ifdef __TIZEN__
105     ret = pthread_mutex_destroy(&m->mutex);
106     if (ret != 0)
107         pa_log_error("pthread_mutex_destroy [%p] error [%d], (%d/%d)", &m->mutex, ret, m->lock, m->unlock);
108     pa_assert_se(ret == 0);
109 #else
110     pa_assert_se(pthread_mutex_destroy(&m->mutex) == 0);
111 #endif
112     pa_xfree(m);
113 }
114
115 void pa_mutex_lock(pa_mutex *m) {
116 #ifdef __TIZEN__
117     int ret;
118 #endif
119     pa_assert(m);
120
121 #ifdef __TIZEN__
122     ret = pthread_mutex_lock(&m->mutex);
123     if (ret != 0)
124         pa_log_error("pthread_mutex_lock [%p] error [%d], (%d/%d)", &m->mutex, ret, m->lock, m->unlock);
125     pa_assert_se(ret == 0);
126     m->lock++;
127 #else
128     pa_assert_se(pthread_mutex_lock(&m->mutex) == 0);
129 #endif
130 }
131
132 bool pa_mutex_try_lock(pa_mutex *m) {
133     int r;
134     pa_assert(m);
135
136     if ((r = pthread_mutex_trylock(&m->mutex)) != 0) {
137         pa_assert(r == EBUSY);
138         return false;
139     }
140
141     return true;
142 }
143
144 void pa_mutex_unlock(pa_mutex *m) {
145     int err;
146
147     pa_assert(m);
148
149     if ((err = pthread_mutex_unlock(&m->mutex)) != 0) {
150 #ifdef __TIZEN__
151         pa_log_error("pthread_mutex_unlock [%p] error [%d], (%d/%d)", &m->mutex, err, m->lock, m->unlock);
152 #else
153         pa_log("pthread_mutex_unlock() failed: %s", pa_cstrerror(err));
154 #endif
155         pa_assert_not_reached();
156     }
157 #ifdef __TIZEN__
158     m->unlock++;
159 #endif
160 }
161
162 pa_cond *pa_cond_new(void) {
163     pa_cond *c;
164
165     c = pa_xnew(pa_cond, 1);
166     pa_assert_se(pthread_cond_init(&c->cond, NULL) == 0);
167     return c;
168 }
169
170 void pa_cond_free(pa_cond *c) {
171     pa_assert(c);
172
173     pa_assert_se(pthread_cond_destroy(&c->cond) == 0);
174     pa_xfree(c);
175 }
176
177 void pa_cond_signal(pa_cond *c, int broadcast) {
178     pa_assert(c);
179
180     if (broadcast)
181         pa_assert_se(pthread_cond_broadcast(&c->cond) == 0);
182     else
183         pa_assert_se(pthread_cond_signal(&c->cond) == 0);
184 }
185
186 int pa_cond_wait(pa_cond *c, pa_mutex *m) {
187     pa_assert(c);
188     pa_assert(m);
189
190     return pthread_cond_wait(&c->cond, &m->mutex);
191 }
192
193 #ifdef __TIZEN__
194 int pa_cond_timedwait(pa_cond *c, pa_mutex *m, int ms_to_wait) {
195     struct timeval now;
196     struct timeval wait;
197     struct timeval wait_until;
198     struct timespec wait_until_ts;
199
200     pa_assert(c);
201     pa_assert(m);
202
203     gettimeofday(&now, NULL);
204
205     wait.tv_sec = ms_to_wait / 1000L;
206     wait.tv_usec = (ms_to_wait % 1000L) * 1000L;
207
208     timeradd(&now, &wait, &wait_until);
209
210     wait_until_ts.tv_sec = wait_until.tv_sec;
211     wait_until_ts.tv_nsec = wait_until.tv_usec * 1000L;
212
213     return pthread_cond_timedwait(&c->cond, &m->mutex, &wait_until_ts);
214 }
215 #endif
216 pa_mutex* pa_static_mutex_get(pa_static_mutex *s, bool recursive, bool inherit_priority) {
217     pa_mutex *m;
218
219     pa_assert(s);
220
221     /* First, check if already initialized and short cut */
222     if ((m = pa_atomic_ptr_load(&s->ptr)))
223         return m;
224
225     /* OK, not initialized, so let's allocate, and fill in */
226     m = pa_mutex_new(recursive, inherit_priority);
227     if ((pa_atomic_ptr_cmpxchg(&s->ptr, NULL, m)))
228         return m;
229
230     pa_mutex_free(m);
231
232     /* Him, filling in failed, so someone else must have filled in
233      * already */
234     pa_assert_se(m = pa_atomic_ptr_load(&s->ptr));
235     return m;
236 }