This source file includes following definitions.
- glwthread_waitqueue_init
- glwthread_waitqueue_add
- glwthread_waitqueue_notify_first
- glwthread_waitqueue_notify_all
- glwthread_rwlock_init
- glwthread_rwlock_rdlock
- glwthread_rwlock_wrlock
- glwthread_rwlock_tryrdlock
- glwthread_rwlock_trywrlock
- glwthread_rwlock_unlock
- glwthread_rwlock_destroy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23 #include "windows-rwlock.h"
24
25 #include <errno.h>
26 #include <stdlib.h>
27
28
29 #undef CreateEvent
30 #define CreateEvent CreateEventA
31
32
33 #define glwthread_waitqueue_t glwthread_carray_waitqueue_t
34
35 static void
36 glwthread_waitqueue_init (glwthread_waitqueue_t *wq)
37 {
38 wq->array = NULL;
39 wq->count = 0;
40 wq->alloc = 0;
41 wq->offset = 0;
42 }
43
44
45
46 static HANDLE
47 glwthread_waitqueue_add (glwthread_waitqueue_t *wq)
48 {
49 HANDLE event;
50 unsigned int index;
51
52 if (wq->count == wq->alloc)
53 {
54 unsigned int new_alloc = 2 * wq->alloc + 1;
55 HANDLE *new_array =
56 (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
57 if (new_array == NULL)
58
59 return INVALID_HANDLE_VALUE;
60
61
62 if (wq->offset > 0)
63 {
64 unsigned int old_count = wq->count;
65 unsigned int old_alloc = wq->alloc;
66 unsigned int old_offset = wq->offset;
67 unsigned int i;
68 if (old_offset + old_count > old_alloc)
69 {
70 unsigned int limit = old_offset + old_count - old_alloc;
71 for (i = 0; i < limit; i++)
72 new_array[old_alloc + i] = new_array[i];
73 }
74 for (i = 0; i < old_count; i++)
75 new_array[i] = new_array[old_offset + i];
76 wq->offset = 0;
77 }
78 wq->array = new_array;
79 wq->alloc = new_alloc;
80 }
81
82
83 event = CreateEvent (NULL, TRUE, FALSE, NULL);
84 if (event == INVALID_HANDLE_VALUE)
85
86 return INVALID_HANDLE_VALUE;
87 index = wq->offset + wq->count;
88 if (index >= wq->alloc)
89 index -= wq->alloc;
90 wq->array[index] = event;
91 wq->count++;
92 return event;
93 }
94
95
96 static void
97 glwthread_waitqueue_notify_first (glwthread_waitqueue_t *wq)
98 {
99 SetEvent (wq->array[wq->offset + 0]);
100 wq->offset++;
101 wq->count--;
102 if (wq->count == 0 || wq->offset == wq->alloc)
103 wq->offset = 0;
104 }
105
106
107 static void
108 glwthread_waitqueue_notify_all (glwthread_waitqueue_t *wq)
109 {
110 unsigned int i;
111
112 for (i = 0; i < wq->count; i++)
113 {
114 unsigned int index = wq->offset + i;
115 if (index >= wq->alloc)
116 index -= wq->alloc;
117 SetEvent (wq->array[index]);
118 }
119 wq->count = 0;
120 wq->offset = 0;
121 }
122
123 void
124 glwthread_rwlock_init (glwthread_rwlock_t *lock)
125 {
126 InitializeCriticalSection (&lock->lock);
127 glwthread_waitqueue_init (&lock->waiting_readers);
128 glwthread_waitqueue_init (&lock->waiting_writers);
129 lock->runcount = 0;
130 lock->guard.done = 1;
131 }
132
133 int
134 glwthread_rwlock_rdlock (glwthread_rwlock_t *lock)
135 {
136 if (!lock->guard.done)
137 {
138 if (InterlockedIncrement (&lock->guard.started) == 0)
139
140 glwthread_rwlock_init (lock);
141 else
142 {
143
144 InterlockedDecrement (&lock->guard.started);
145
146
147 while (!lock->guard.done)
148 Sleep (0);
149 }
150 }
151 EnterCriticalSection (&lock->lock);
152
153
154
155
156 if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
157 {
158
159
160 HANDLE event = glwthread_waitqueue_add (&lock->waiting_readers);
161 if (event != INVALID_HANDLE_VALUE)
162 {
163 DWORD result;
164 LeaveCriticalSection (&lock->lock);
165
166 result = WaitForSingleObject (event, INFINITE);
167 if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
168 abort ();
169 CloseHandle (event);
170
171
172 if (!(lock->runcount > 0))
173 abort ();
174 return 0;
175 }
176 else
177 {
178
179 do
180 {
181 LeaveCriticalSection (&lock->lock);
182 Sleep (1);
183 EnterCriticalSection (&lock->lock);
184 }
185 while (!(lock->runcount + 1 > 0));
186 }
187 }
188 lock->runcount++;
189 LeaveCriticalSection (&lock->lock);
190 return 0;
191 }
192
193 int
194 glwthread_rwlock_wrlock (glwthread_rwlock_t *lock)
195 {
196 if (!lock->guard.done)
197 {
198 if (InterlockedIncrement (&lock->guard.started) == 0)
199
200 glwthread_rwlock_init (lock);
201 else
202 {
203
204 InterlockedDecrement (&lock->guard.started);
205
206
207 while (!lock->guard.done)
208 Sleep (0);
209 }
210 }
211 EnterCriticalSection (&lock->lock);
212
213 if (!(lock->runcount == 0))
214 {
215
216
217 HANDLE event = glwthread_waitqueue_add (&lock->waiting_writers);
218 if (event != INVALID_HANDLE_VALUE)
219 {
220 DWORD result;
221 LeaveCriticalSection (&lock->lock);
222
223 result = WaitForSingleObject (event, INFINITE);
224 if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
225 abort ();
226 CloseHandle (event);
227
228
229 if (!(lock->runcount == -1))
230 abort ();
231 return 0;
232 }
233 else
234 {
235
236 do
237 {
238 LeaveCriticalSection (&lock->lock);
239 Sleep (1);
240 EnterCriticalSection (&lock->lock);
241 }
242 while (!(lock->runcount == 0));
243 }
244 }
245 lock->runcount--;
246 LeaveCriticalSection (&lock->lock);
247 return 0;
248 }
249
250 int
251 glwthread_rwlock_tryrdlock (glwthread_rwlock_t *lock)
252 {
253 if (!lock->guard.done)
254 {
255 if (InterlockedIncrement (&lock->guard.started) == 0)
256
257 glwthread_rwlock_init (lock);
258 else
259 {
260
261 InterlockedDecrement (&lock->guard.started);
262
263
264 while (!lock->guard.done)
265 Sleep (0);
266 }
267 }
268
269
270 EnterCriticalSection (&lock->lock);
271
272
273
274
275 if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
276 {
277
278 LeaveCriticalSection (&lock->lock);
279 return EBUSY;
280 }
281 lock->runcount++;
282 LeaveCriticalSection (&lock->lock);
283 return 0;
284 }
285
286 int
287 glwthread_rwlock_trywrlock (glwthread_rwlock_t *lock)
288 {
289 if (!lock->guard.done)
290 {
291 if (InterlockedIncrement (&lock->guard.started) == 0)
292
293 glwthread_rwlock_init (lock);
294 else
295 {
296
297 InterlockedDecrement (&lock->guard.started);
298
299
300 while (!lock->guard.done)
301 Sleep (0);
302 }
303 }
304
305
306 EnterCriticalSection (&lock->lock);
307
308 if (!(lock->runcount == 0))
309 {
310
311 LeaveCriticalSection (&lock->lock);
312 return EBUSY;
313 }
314 lock->runcount--;
315 LeaveCriticalSection (&lock->lock);
316 return 0;
317 }
318
319 int
320 glwthread_rwlock_unlock (glwthread_rwlock_t *lock)
321 {
322 if (!lock->guard.done)
323 return EINVAL;
324 EnterCriticalSection (&lock->lock);
325 if (lock->runcount < 0)
326 {
327
328 if (!(lock->runcount == -1))
329 abort ();
330 lock->runcount = 0;
331 }
332 else
333 {
334
335 if (!(lock->runcount > 0))
336 {
337 LeaveCriticalSection (&lock->lock);
338 return EPERM;
339 }
340 lock->runcount--;
341 }
342 if (lock->runcount == 0)
343 {
344
345
346 if (lock->waiting_writers.count > 0)
347 {
348
349 lock->runcount--;
350 glwthread_waitqueue_notify_first (&lock->waiting_writers);
351 }
352 else
353 {
354
355 lock->runcount += lock->waiting_readers.count;
356 glwthread_waitqueue_notify_all (&lock->waiting_readers);
357 }
358 }
359 LeaveCriticalSection (&lock->lock);
360 return 0;
361 }
362
363 int
364 glwthread_rwlock_destroy (glwthread_rwlock_t *lock)
365 {
366 if (!lock->guard.done)
367 return EINVAL;
368 if (lock->runcount != 0)
369 return EBUSY;
370 DeleteCriticalSection (&lock->lock);
371 if (lock->waiting_readers.array != NULL)
372 free (lock->waiting_readers.array);
373 if (lock->waiting_writers.array != NULL)
374 free (lock->waiting_writers.array);
375 lock->guard.done = 0;
376 return 0;
377 }