This source file includes following definitions.
- pthread_rwlockattr_init
- pthread_rwlockattr_destroy
- pthread_rwlock_init
- pthread_rwlock_rdlock
- pthread_rwlock_wrlock
- pthread_rwlock_tryrdlock
- pthread_rwlock_trywrlock
- pthread_rwlock_timedrdlock
- pthread_rwlock_timedwrlock
- pthread_rwlock_unlock
- pthread_rwlock_destroy
- pthread_rwlock_init
- pthread_rwlock_rdlock
- pthread_rwlock_wrlock
- pthread_rwlock_tryrdlock
- pthread_rwlock_trywrlock
- pthread_rwlock_timedrdlock
- pthread_rwlock_timedwrlock
- pthread_rwlock_unlock
- pthread_rwlock_destroy
- pthread_rwlock_timedrdlock
- pthread_rwlock_timedwrlock
- pthread_rwlock_init
- pthread_rwlock_rdlock
- pthread_rwlock_wrlock
- pthread_rwlock_tryrdlock
- pthread_rwlock_trywrlock
- pthread_rwlock_timedrdlock
- pthread_rwlock_timedwrlock
- pthread_rwlock_unlock
- pthread_rwlock_destroy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <config.h>
20
21
22 #include <pthread.h>
23
24 #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
25 # include "windows-timedrwlock.h"
26 #else
27 # include <errno.h>
28 # include <limits.h>
29 # include <sys/time.h>
30 # include <time.h>
31 #endif
32
33 #if ((defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS) || !HAVE_PTHREAD_H
34
35 int
36 pthread_rwlockattr_init (pthread_rwlockattr_t *attr)
37 {
38 *attr = 0;
39 return 0;
40 }
41
42 int
43 pthread_rwlockattr_destroy (_GL_UNUSED pthread_rwlockattr_t *attr)
44 {
45 return 0;
46 }
47
48 #endif
49
50 #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
51
52
53 int
54 pthread_rwlock_init (pthread_rwlock_t *lock,
55 _GL_UNUSED const pthread_rwlockattr_t *attr)
56 {
57 glwthread_timedrwlock_init (lock);
58 return 0;
59 }
60
61 int
62 pthread_rwlock_rdlock (pthread_rwlock_t *lock)
63 {
64 return glwthread_timedrwlock_rdlock (lock);
65 }
66
67 int
68 pthread_rwlock_wrlock (pthread_rwlock_t *lock)
69 {
70 return glwthread_timedrwlock_wrlock (lock);
71 }
72
73 int
74 pthread_rwlock_tryrdlock (pthread_rwlock_t *lock)
75 {
76 return glwthread_timedrwlock_tryrdlock (lock);
77 }
78
79 int
80 pthread_rwlock_trywrlock (pthread_rwlock_t *lock)
81 {
82 return glwthread_timedrwlock_trywrlock (lock);
83 }
84
85 int
86 pthread_rwlock_timedrdlock (pthread_rwlock_t *lock,
87 const struct timespec *abstime)
88 {
89 return glwthread_timedrwlock_timedrdlock (lock, abstime);
90 }
91
92 int
93 pthread_rwlock_timedwrlock (pthread_rwlock_t *lock,
94 const struct timespec *abstime)
95 {
96 return glwthread_timedrwlock_timedwrlock (lock, abstime);
97 }
98
99 int
100 pthread_rwlock_unlock (pthread_rwlock_t *lock)
101 {
102 return glwthread_timedrwlock_unlock (lock);
103 }
104
105 int
106 pthread_rwlock_destroy (pthread_rwlock_t *lock)
107 {
108 return glwthread_timedrwlock_destroy (lock);
109 }
110
111 #elif HAVE_PTHREAD_H
112
113
114 # if PTHREAD_RWLOCK_UNIMPLEMENTED
115
116 int
117 pthread_rwlock_init (pthread_rwlock_t *lock,
118 _GL_UNUSED const pthread_rwlockattr_t *attr)
119 {
120 int err;
121
122 err = pthread_mutex_init (&lock->lock, NULL);
123 if (err != 0)
124 return err;
125 err = pthread_cond_init (&lock->waiting_readers, NULL);
126 if (err != 0)
127 return err;
128 err = pthread_cond_init (&lock->waiting_writers, NULL);
129 if (err != 0)
130 return err;
131 lock->waiting_writers_count = 0;
132 lock->runcount = 0;
133 return 0;
134 }
135
136 int
137 pthread_rwlock_rdlock (pthread_rwlock_t *lock)
138 {
139 int err;
140
141 err = pthread_mutex_lock (&lock->lock);
142 if (err != 0)
143 return err;
144
145
146
147
148 while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
149 {
150
151
152 err = pthread_cond_wait (&lock->waiting_readers, &lock->lock);
153 if (err != 0)
154 {
155 pthread_mutex_unlock (&lock->lock);
156 return err;
157 }
158 }
159 lock->runcount++;
160 return pthread_mutex_unlock (&lock->lock);
161 }
162
163 int
164 pthread_rwlock_wrlock (pthread_rwlock_t *lock)
165 {
166 int err;
167
168 err = pthread_mutex_lock (&lock->lock);
169 if (err != 0)
170 return err;
171
172 while (!(lock->runcount == 0))
173 {
174
175
176 lock->waiting_writers_count++;
177 err = pthread_cond_wait (&lock->waiting_writers, &lock->lock);
178 if (err != 0)
179 {
180 lock->waiting_writers_count--;
181 pthread_mutex_unlock (&lock->lock);
182 return err;
183 }
184 lock->waiting_writers_count--;
185 }
186 lock->runcount--;
187 return pthread_mutex_unlock (&lock->lock);
188 }
189
190 int
191 pthread_rwlock_tryrdlock (pthread_rwlock_t *lock)
192 {
193 int err;
194
195 err = pthread_mutex_lock (&lock->lock);
196 if (err != 0)
197 return err;
198
199
200
201
202 if (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
203 {
204
205 pthread_mutex_unlock (&lock->lock);
206 return EBUSY;
207 }
208 lock->runcount++;
209 return pthread_mutex_unlock (&lock->lock);
210 }
211
212 int
213 pthread_rwlock_trywrlock (pthread_rwlock_t *lock)
214 {
215 int err;
216
217 err = pthread_mutex_lock (&lock->lock);
218 if (err != 0)
219 return err;
220
221 if (!(lock->runcount == 0))
222 {
223
224 pthread_mutex_unlock (&lock->lock);
225 return EBUSY;
226 }
227 lock->runcount--;
228 return pthread_mutex_unlock (&lock->lock);
229 }
230
231 int
232 pthread_rwlock_timedrdlock (pthread_rwlock_t *lock,
233 const struct timespec *abstime)
234 {
235 int err;
236
237 err = pthread_mutex_lock (&lock->lock);
238 if (err != 0)
239 return err;
240
241
242
243
244 while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
245 {
246
247
248 err = pthread_cond_timedwait (&lock->waiting_readers, &lock->lock,
249 abstime);
250 if (err != 0)
251 {
252 pthread_mutex_unlock (&lock->lock);
253 return err;
254 }
255 }
256 lock->runcount++;
257 return pthread_mutex_unlock (&lock->lock);
258 }
259
260 int
261 pthread_rwlock_timedwrlock (pthread_rwlock_t *lock,
262 const struct timespec *abstime)
263 {
264 int err;
265
266 err = pthread_mutex_lock (&lock->lock);
267 if (err != 0)
268 return err;
269
270 while (!(lock->runcount == 0))
271 {
272
273
274 lock->waiting_writers_count++;
275 err = pthread_cond_timedwait (&lock->waiting_writers, &lock->lock,
276 abstime);
277 if (err != 0)
278 {
279 lock->waiting_writers_count--;
280 pthread_mutex_unlock (&lock->lock);
281 return err;
282 }
283 lock->waiting_writers_count--;
284 }
285 lock->runcount--;
286 return pthread_mutex_unlock (&lock->lock);
287 }
288
289 int
290 pthread_rwlock_unlock (pthread_rwlock_t *lock)
291 {
292 int err;
293
294 err = pthread_mutex_lock (&lock->lock);
295 if (err != 0)
296 return err;
297 if (lock->runcount < 0)
298 {
299
300 if (!(lock->runcount == -1))
301 {
302 pthread_mutex_unlock (&lock->lock);
303 return EINVAL;
304 }
305 lock->runcount = 0;
306 }
307 else
308 {
309
310 if (!(lock->runcount > 0))
311 {
312 pthread_mutex_unlock (&lock->lock);
313 return EINVAL;
314 }
315 lock->runcount--;
316 }
317 if (lock->runcount == 0)
318 {
319
320
321 if (lock->waiting_writers_count > 0)
322 {
323
324 err = pthread_cond_signal (&lock->waiting_writers);
325 if (err != 0)
326 {
327 pthread_mutex_unlock (&lock->lock);
328 return err;
329 }
330 }
331 else
332 {
333
334 err = pthread_cond_broadcast (&lock->waiting_readers);
335 if (err != 0)
336 {
337 pthread_mutex_unlock (&lock->lock);
338 return err;
339 }
340 }
341 }
342 return pthread_mutex_unlock (&lock->lock);
343 }
344
345 int
346 pthread_rwlock_destroy (pthread_rwlock_t *lock)
347 {
348 int err;
349
350 err = pthread_mutex_destroy (&lock->lock);
351 if (err != 0)
352 return err;
353 err = pthread_cond_destroy (&lock->waiting_readers);
354 if (err != 0)
355 return err;
356 err = pthread_cond_destroy (&lock->waiting_writers);
357 if (err != 0)
358 return err;
359 return 0;
360 }
361
362 # elif PTHREAD_RWLOCK_LACKS_TIMEOUT
363
364 int
365 pthread_rwlock_timedrdlock (pthread_rwlock_t *lock,
366 const struct timespec *abstime)
367 {
368
369 for (;;)
370 {
371 int err;
372 struct timeval currtime;
373 unsigned long remaining;
374 struct timespec duration;
375
376 err = pthread_rwlock_tryrdlock (lock);
377 if (err != EBUSY)
378 return err;
379
380 gettimeofday (&currtime, NULL);
381
382 if (currtime.tv_sec > abstime->tv_sec)
383 remaining = 0;
384 else
385 {
386 unsigned long seconds = abstime->tv_sec - currtime.tv_sec;
387 remaining = seconds * 1000000000;
388 if (remaining / 1000000000 != seconds)
389 remaining = ULONG_MAX;
390 else
391 {
392 long nanoseconds =
393 abstime->tv_nsec - currtime.tv_usec * 1000;
394 if (nanoseconds >= 0)
395 {
396 remaining += nanoseconds;
397 if (remaining < nanoseconds)
398 remaining = ULONG_MAX;
399 }
400 else
401 {
402 if (remaining >= - nanoseconds)
403 remaining -= (- nanoseconds);
404 else
405 remaining = 0;
406 }
407 }
408 }
409 if (remaining == 0)
410 return ETIMEDOUT;
411
412
413 duration.tv_sec = 0;
414 duration.tv_nsec = 1000000;
415 if (duration.tv_nsec > remaining)
416 duration.tv_nsec = remaining;
417 nanosleep (&duration, NULL);
418 }
419 }
420
421 int
422 pthread_rwlock_timedwrlock (pthread_rwlock_t *lock,
423 const struct timespec *abstime)
424 {
425
426 for (;;)
427 {
428 int err;
429 struct timeval currtime;
430 unsigned long remaining;
431 struct timespec duration;
432
433 err = pthread_rwlock_trywrlock (lock);
434 if (err != EBUSY)
435 return err;
436
437 gettimeofday (&currtime, NULL);
438
439 if (currtime.tv_sec > abstime->tv_sec)
440 remaining = 0;
441 else
442 {
443 unsigned long seconds = abstime->tv_sec - currtime.tv_sec;
444 remaining = seconds * 1000000000;
445 if (remaining / 1000000000 != seconds)
446 remaining = ULONG_MAX;
447 else
448 {
449 long nanoseconds =
450 abstime->tv_nsec - currtime.tv_usec * 1000;
451 if (nanoseconds >= 0)
452 {
453 remaining += nanoseconds;
454 if (remaining < nanoseconds)
455 remaining = ULONG_MAX;
456 }
457 else
458 {
459 if (remaining >= - nanoseconds)
460 remaining -= (- nanoseconds);
461 else
462 remaining = 0;
463 }
464 }
465 }
466 if (remaining == 0)
467 return ETIMEDOUT;
468
469
470 duration.tv_sec = 0;
471 duration.tv_nsec = 1000000;
472 if (duration.tv_nsec > remaining)
473 duration.tv_nsec = remaining;
474 nanosleep (&duration, NULL);
475 }
476 }
477
478 # endif
479
480 #else
481
482
483
484
485
486 int
487 pthread_rwlock_init (pthread_rwlock_t *lock,
488 _GL_UNUSED const pthread_rwlockattr_t *attr)
489 {
490 *lock = 0;
491 return 0;
492 }
493
494 int
495 pthread_rwlock_rdlock (pthread_rwlock_t *lock)
496 {
497 if (*lock < 0)
498 return EDEADLK;
499 (*lock)++;
500 return 0;
501 }
502
503 int
504 pthread_rwlock_wrlock (pthread_rwlock_t *lock)
505 {
506 if (*lock != 0)
507 return EDEADLK;
508 *lock = -1;
509 return 0;
510 }
511
512 int
513 pthread_rwlock_tryrdlock (pthread_rwlock_t *lock)
514 {
515 return pthread_rwlock_rdlock (lock);
516 }
517
518 int
519 pthread_rwlock_trywrlock (pthread_rwlock_t *lock)
520 {
521 return pthread_rwlock_wrlock (lock);
522 }
523
524 int
525 pthread_rwlock_timedrdlock (pthread_rwlock_t *lock,
526 _GL_UNUSED const struct timespec *abstime)
527 {
528 return pthread_rwlock_rdlock (lock);
529 }
530
531 int
532 pthread_rwlock_timedwrlock (pthread_rwlock_t *lock,
533 _GL_UNUSED const struct timespec *abstime)
534 {
535 return pthread_rwlock_wrlock (lock);
536 }
537
538 int
539 pthread_rwlock_unlock (pthread_rwlock_t *lock)
540 {
541 if (*lock == 0)
542 return EPERM;
543 if (*lock < 0)
544 *lock = 0;
545 else
546 (*lock)--;
547 return 0;
548 }
549
550 int
551 pthread_rwlock_destroy (pthread_rwlock_t *lock)
552 {
553 if (*lock)
554 return EBUSY;
555 return 0;
556 }
557
558 #endif