1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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 <windows.h>
25
26 #include <pulse/xmalloc.h>
27 #include <pulsecore/hashmap.h>
28
29 #include "mutex.h"
30
31 struct pa_mutex {
32 CRITICAL_SECTION mutex;
33 };
34
35 struct pa_cond {
36 pa_hashmap *wait_events;
37 };
38
pa_mutex_new(bool recursive,bool inherit_priority)39 pa_mutex* pa_mutex_new(bool recursive, bool inherit_priority) {
40 pa_mutex *m;
41
42 m = pa_xnew(pa_mutex, 1);
43
44 InitializeCriticalSection(&m->mutex);
45
46 return m;
47 }
48
pa_mutex_free(pa_mutex * m)49 void pa_mutex_free(pa_mutex *m) {
50 assert(m);
51
52 DeleteCriticalSection(&m->mutex);
53 pa_xfree(m);
54 }
55
pa_mutex_lock(pa_mutex * m)56 void pa_mutex_lock(pa_mutex *m) {
57 assert(m);
58
59 EnterCriticalSection(&m->mutex);
60 }
61
pa_mutex_unlock(pa_mutex * m)62 void pa_mutex_unlock(pa_mutex *m) {
63 assert(m);
64
65 LeaveCriticalSection(&m->mutex);
66 }
67
pa_cond_new(void)68 pa_cond *pa_cond_new(void) {
69 pa_cond *c;
70
71 c = pa_xnew(pa_cond, 1);
72 c->wait_events = pa_hashmap_new(NULL, NULL);
73 assert(c->wait_events);
74
75 return c;
76 }
77
pa_cond_free(pa_cond * c)78 void pa_cond_free(pa_cond *c) {
79 assert(c);
80
81 pa_hashmap_free(c->wait_events);
82 pa_xfree(c);
83 }
84
pa_cond_signal(pa_cond * c,int broadcast)85 void pa_cond_signal(pa_cond *c, int broadcast) {
86 assert(c);
87
88 if (pa_hashmap_size(c->wait_events) == 0)
89 return;
90
91 if (broadcast)
92 SetEvent(pa_hashmap_first(c->wait_events));
93 else {
94 void *iter;
95 const void *key;
96 HANDLE event;
97
98 iter = NULL;
99 while (1) {
100 pa_hashmap_iterate(c->wait_events, &iter, &key);
101 if (key == NULL)
102 break;
103 event = (HANDLE)pa_hashmap_get(c->wait_events, key);
104 SetEvent(event);
105 }
106 }
107 }
108
pa_cond_wait(pa_cond * c,pa_mutex * m)109 int pa_cond_wait(pa_cond *c, pa_mutex *m) {
110 HANDLE event;
111
112 assert(c);
113 assert(m);
114
115 event = CreateEvent(NULL, FALSE, FALSE, NULL);
116 assert(event);
117
118 pa_hashmap_put(c->wait_events, event, event);
119
120 pa_mutex_unlock(m);
121
122 WaitForSingleObject(event, INFINITE);
123
124 pa_mutex_lock(m);
125
126 pa_hashmap_remove(c->wait_events, event);
127
128 CloseHandle(event);
129
130 return 0;
131 }
132
133 /* This is a copy of the function in mutex-posix.c */
pa_static_mutex_get(pa_static_mutex * s,bool recursive,bool inherit_priority)134 pa_mutex* pa_static_mutex_get(pa_static_mutex *s, bool recursive, bool inherit_priority) {
135 pa_mutex *m;
136
137 pa_assert(s);
138
139 /* First, check if already initialized and short cut */
140 if ((m = pa_atomic_ptr_load(&s->ptr)))
141 return m;
142
143 /* OK, not initialized, so let's allocate, and fill in */
144 m = pa_mutex_new(recursive, inherit_priority);
145 if ((pa_atomic_ptr_cmpxchg(&s->ptr, NULL, m)))
146 return m;
147
148 pa_mutex_free(m);
149
150 /* Him, filling in failed, so someone else must have filled in
151 * already */
152 pa_assert_se(m = pa_atomic_ptr_load(&s->ptr));
153 return m;
154 }
155