Branch data Line data Source code
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, write to the Free Software
18 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 : : USA.
20 : : ***/
21 : :
22 : : #ifdef HAVE_CONFIG_H
23 : : #include <config.h>
24 : : #endif
25 : :
26 : : #include <pthread.h>
27 : : #include <errno.h>
28 : :
29 : : #include <pulse/xmalloc.h>
30 : : #include <pulsecore/macro.h>
31 : :
32 : : #include "mutex.h"
33 : :
34 : : struct pa_mutex {
35 : : pthread_mutex_t mutex;
36 : : };
37 : :
38 : : struct pa_cond {
39 : : pthread_cond_t cond;
40 : : };
41 : :
42 : 1052 : pa_mutex* pa_mutex_new(pa_bool_t recursive, pa_bool_t inherit_priority) {
43 : : pa_mutex *m;
44 : : pthread_mutexattr_t attr;
45 : : int r;
46 : :
47 [ - + ]: 1052 : pa_assert_se(pthread_mutexattr_init(&attr) == 0);
48 : :
49 [ + + ]: 1047 : if (recursive)
50 [ - + ]: 24 : pa_assert_se(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);
51 : :
52 : : #ifdef HAVE_PTHREAD_PRIO_INHERIT
53 [ + + ]: 1047 : if (inherit_priority) {
54 : 27 : r = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
55 [ - + ]: 27 : pa_assert(r == 0 || r == ENOTSUP);
56 : : }
57 : : #endif
58 : :
59 : 1047 : m = pa_xnew(pa_mutex, 1);
60 : :
61 : : #ifndef HAVE_PTHREAD_PRIO_INHERIT
62 : : pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
63 : :
64 : : #else
65 [ - + ]: 1046 : if ((r = pthread_mutex_init(&m->mutex, &attr))) {
66 : :
67 : : /* If this failed, then this was probably due to non-available
68 : : * priority inheritance. In which case we fall back to normal
69 : : * mutexes. */
70 [ # # ][ # # ]: 0 : pa_assert(r == ENOTSUP && inherit_priority);
71 : :
72 [ # # ]: 0 : pa_assert_se(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_NONE) == 0);
73 [ # # ]: 0 : pa_assert_se(pthread_mutex_init(&m->mutex, &attr) == 0);
74 : : }
75 : : #endif
76 : :
77 : 1048 : return m;
78 : : }
79 : :
80 : 500 : void pa_mutex_free(pa_mutex *m) {
81 [ - + ]: 500 : pa_assert(m);
82 : :
83 [ - + ]: 500 : pa_assert_se(pthread_mutex_destroy(&m->mutex) == 0);
84 : 500 : pa_xfree(m);
85 : 497 : }
86 : :
87 : 1734 : void pa_mutex_lock(pa_mutex *m) {
88 [ - + ]: 1734 : pa_assert(m);
89 : :
90 [ - + ]: 1734 : pa_assert_se(pthread_mutex_lock(&m->mutex) == 0);
91 : 1774 : }
92 : :
93 : 0 : pa_bool_t pa_mutex_try_lock(pa_mutex *m) {
94 : : int r;
95 [ # # ]: 0 : pa_assert(m);
96 : :
97 [ # # ]: 0 : if ((r = pthread_mutex_trylock(&m->mutex)) != 0) {
98 [ # # ]: 0 : pa_assert(r == EBUSY);
99 : : return FALSE;
100 : : }
101 : :
102 : : return TRUE;
103 : : }
104 : :
105 : 1775 : void pa_mutex_unlock(pa_mutex *m) {
106 [ - + ]: 1775 : pa_assert(m);
107 : :
108 [ - + ]: 1775 : pa_assert_se(pthread_mutex_unlock(&m->mutex) == 0);
109 : 1766 : }
110 : :
111 : 4 : pa_cond *pa_cond_new(void) {
112 : : pa_cond *c;
113 : :
114 : 4 : c = pa_xnew(pa_cond, 1);
115 [ - + ]: 4 : pa_assert_se(pthread_cond_init(&c->cond, NULL) == 0);
116 : 4 : return c;
117 : : }
118 : :
119 : 4 : void pa_cond_free(pa_cond *c) {
120 [ - + ]: 4 : pa_assert(c);
121 : :
122 [ - + ]: 4 : pa_assert_se(pthread_cond_destroy(&c->cond) == 0);
123 : 4 : pa_xfree(c);
124 : 4 : }
125 : :
126 : 203 : void pa_cond_signal(pa_cond *c, int broadcast) {
127 [ - + ]: 203 : pa_assert(c);
128 : :
129 [ + + ]: 203 : if (broadcast)
130 [ - + ]: 2 : pa_assert_se(pthread_cond_broadcast(&c->cond) == 0);
131 : : else
132 [ - + ]: 201 : pa_assert_se(pthread_cond_signal(&c->cond) == 0);
133 : 203 : }
134 : :
135 : 137 : int pa_cond_wait(pa_cond *c, pa_mutex *m) {
136 [ - + ]: 137 : pa_assert(c);
137 [ - + ]: 137 : pa_assert(m);
138 : :
139 : 137 : return pthread_cond_wait(&c->cond, &m->mutex);
140 : : }
141 : :
142 : 1990 : pa_mutex* pa_static_mutex_get(pa_static_mutex *s, pa_bool_t recursive, pa_bool_t inherit_priority) {
143 : : pa_mutex *m;
144 : :
145 [ - + ]: 1990 : pa_assert(s);
146 : :
147 : : /* First, check if already initialized and short cut */
148 [ + + ]: 1990 : if ((m = pa_atomic_ptr_load(&s->ptr)))
149 : : return m;
150 : :
151 : : /* OK, not initialized, so let's allocate, and fill in */
152 : 1024 : m = pa_mutex_new(recursive, inherit_priority);
153 [ + + ]: 1015 : if ((pa_atomic_ptr_cmpxchg(&s->ptr, NULL, m)))
154 : : return m;
155 : :
156 : 477 : pa_mutex_free(m);
157 : :
158 : : /* Him, filling in failed, so someone else must have filled in
159 : : * already */
160 [ - + ]: 1974 : pa_assert_se(m = pa_atomic_ptr_load(&s->ptr));
161 : : return m;
162 : : }
|