This source file includes following definitions.
- glthread_lock_init
- glthread_lock_lock
- glthread_lock_unlock
- glthread_lock_destroy
- glthread_rwlock_init
- glthread_rwlock_rdlock
- glthread_rwlock_wrlock
- glthread_rwlock_unlock
- glthread_rwlock_destroy
- glthread_recursive_lock_init
- glthread_recursive_lock_lock
- glthread_recursive_lock_unlock
- glthread_recursive_lock_destroy
- glthread_rwlock_init_for_glibc
- glthread_rwlock_init_multithreaded
- glthread_rwlock_rdlock_multithreaded
- glthread_rwlock_wrlock_multithreaded
- glthread_rwlock_unlock_multithreaded
- glthread_rwlock_destroy_multithreaded
- glthread_rwlock_init_multithreaded
- glthread_rwlock_rdlock_multithreaded
- glthread_rwlock_wrlock_multithreaded
- glthread_rwlock_unlock_multithreaded
- glthread_rwlock_destroy_multithreaded
- glthread_recursive_lock_init_multithreaded
- glthread_recursive_lock_init_multithreaded
- glthread_recursive_lock_lock_multithreaded
- glthread_recursive_lock_unlock_multithreaded
- glthread_recursive_lock_destroy_multithreaded
- glthread_recursive_lock_init_multithreaded
- glthread_recursive_lock_lock_multithreaded
- glthread_recursive_lock_unlock_multithreaded
- glthread_recursive_lock_destroy_multithreaded
- glthread_once_singlethreaded
- glthread_once_multithreaded
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 #include "glthread/lock.h"
23
24
25
26 #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
27
28
29
30 int
31 glthread_lock_init (gl_lock_t *lock)
32 {
33 if (mtx_init (&lock->mutex, mtx_plain) != thrd_success)
34 return ENOMEM;
35 lock->init_needed = 0;
36 return 0;
37 }
38
39 int
40 glthread_lock_lock (gl_lock_t *lock)
41 {
42 if (lock->init_needed)
43 call_once (&lock->init_once, lock->init_func);
44 if (mtx_lock (&lock->mutex) != thrd_success)
45 return EAGAIN;
46 return 0;
47 }
48
49 int
50 glthread_lock_unlock (gl_lock_t *lock)
51 {
52 if (lock->init_needed)
53 call_once (&lock->init_once, lock->init_func);
54 if (mtx_unlock (&lock->mutex) != thrd_success)
55 return EINVAL;
56 return 0;
57 }
58
59 int
60 glthread_lock_destroy (gl_lock_t *lock)
61 {
62 if (lock->init_needed)
63 call_once (&lock->init_once, lock->init_func);
64 mtx_destroy (&lock->mutex);
65 return 0;
66 }
67
68
69
70 int
71 glthread_rwlock_init (gl_rwlock_t *lock)
72 {
73 if (mtx_init (&lock->lock, mtx_plain) != thrd_success
74 || cnd_init (&lock->waiting_readers) != thrd_success
75 || cnd_init (&lock->waiting_writers) != thrd_success)
76 return ENOMEM;
77 lock->waiting_writers_count = 0;
78 lock->runcount = 0;
79 lock->init_needed = 0;
80 return 0;
81 }
82
83 int
84 glthread_rwlock_rdlock (gl_rwlock_t *lock)
85 {
86 if (lock->init_needed)
87 call_once (&lock->init_once, lock->init_func);
88 if (mtx_lock (&lock->lock) != thrd_success)
89 return EAGAIN;
90
91
92
93
94 while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
95 {
96
97
98 if (cnd_wait (&lock->waiting_readers, &lock->lock) != thrd_success)
99 {
100 mtx_unlock (&lock->lock);
101 return EINVAL;
102 }
103 }
104 lock->runcount++;
105 if (mtx_unlock (&lock->lock) != thrd_success)
106 return EINVAL;
107 return 0;
108 }
109
110 int
111 glthread_rwlock_wrlock (gl_rwlock_t *lock)
112 {
113 if (lock->init_needed)
114 call_once (&lock->init_once, lock->init_func);
115 if (mtx_lock (&lock->lock) != thrd_success)
116 return EAGAIN;
117
118 while (!(lock->runcount == 0))
119 {
120
121
122 lock->waiting_writers_count++;
123 if (cnd_wait (&lock->waiting_writers, &lock->lock) != thrd_success)
124 {
125 lock->waiting_writers_count--;
126 mtx_unlock (&lock->lock);
127 return EINVAL;
128 }
129 lock->waiting_writers_count--;
130 }
131 lock->runcount--;
132 if (mtx_unlock (&lock->lock) != thrd_success)
133 return EINVAL;
134 return 0;
135 }
136
137 int
138 glthread_rwlock_unlock (gl_rwlock_t *lock)
139 {
140 if (lock->init_needed)
141 call_once (&lock->init_once, lock->init_func);
142 if (mtx_lock (&lock->lock) != thrd_success)
143 return EAGAIN;
144 if (lock->runcount < 0)
145 {
146
147 if (!(lock->runcount == -1))
148 {
149 mtx_unlock (&lock->lock);
150 return EINVAL;
151 }
152 lock->runcount = 0;
153 }
154 else
155 {
156
157 if (!(lock->runcount > 0))
158 {
159 mtx_unlock (&lock->lock);
160 return EINVAL;
161 }
162 lock->runcount--;
163 }
164 if (lock->runcount == 0)
165 {
166
167
168 if (lock->waiting_writers_count > 0)
169 {
170
171 if (cnd_signal (&lock->waiting_writers) != thrd_success)
172 {
173 mtx_unlock (&lock->lock);
174 return EINVAL;
175 }
176 }
177 else
178 {
179
180 if (cnd_broadcast (&lock->waiting_readers) != thrd_success)
181 {
182 mtx_unlock (&lock->lock);
183 return EINVAL;
184 }
185 }
186 }
187 if (mtx_unlock (&lock->lock) != thrd_success)
188 return EINVAL;
189 return 0;
190 }
191
192 int
193 glthread_rwlock_destroy (gl_rwlock_t *lock)
194 {
195 if (lock->init_needed)
196 call_once (&lock->init_once, lock->init_func);
197 mtx_destroy (&lock->lock);
198 cnd_destroy (&lock->waiting_readers);
199 cnd_destroy (&lock->waiting_writers);
200 return 0;
201 }
202
203
204
205 int
206 glthread_recursive_lock_init (gl_recursive_lock_t *lock)
207 {
208 if (mtx_init (&lock->mutex, mtx_plain | mtx_recursive) != thrd_success)
209 return ENOMEM;
210 lock->init_needed = 0;
211 return 0;
212 }
213
214 int
215 glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
216 {
217 if (lock->init_needed)
218 call_once (&lock->init_once, lock->init_func);
219 if (mtx_lock (&lock->mutex) != thrd_success)
220 return EAGAIN;
221 return 0;
222 }
223
224 int
225 glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
226 {
227 if (lock->init_needed)
228 call_once (&lock->init_once, lock->init_func);
229 if (mtx_unlock (&lock->mutex) != thrd_success)
230 return EINVAL;
231 return 0;
232 }
233
234 int
235 glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
236 {
237 if (lock->init_needed)
238 call_once (&lock->init_once, lock->init_func);
239 mtx_destroy (&lock->mutex);
240 return 0;
241 }
242
243
244
245 #endif
246
247
248
249 #if USE_POSIX_THREADS
250
251
252
253
254
255 # if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
256
257 # if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
258
259 # if !HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
260
261
262 int
263 glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock)
264 {
265 pthread_rwlockattr_t attributes;
266 int err;
267
268 err = pthread_rwlockattr_init (&attributes);
269 if (err != 0)
270 return err;
271
272
273
274
275 err = pthread_rwlockattr_setkind_np (&attributes,
276 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
277 if (err == 0)
278 err = pthread_rwlock_init(lock, &attributes);
279
280
281 pthread_rwlockattr_destroy (&attributes);
282 return err;
283 }
284
285 # endif
286 # else
287
288 int
289 glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
290 {
291 int err;
292
293 err = pthread_rwlock_init (&lock->rwlock, NULL);
294 if (err != 0)
295 return err;
296 lock->initialized = 1;
297 return 0;
298 }
299
300 int
301 glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
302 {
303 if (!lock->initialized)
304 {
305 int err;
306
307 err = pthread_mutex_lock (&lock->guard);
308 if (err != 0)
309 return err;
310 if (!lock->initialized)
311 {
312 err = glthread_rwlock_init_multithreaded (lock);
313 if (err != 0)
314 {
315 pthread_mutex_unlock (&lock->guard);
316 return err;
317 }
318 }
319 err = pthread_mutex_unlock (&lock->guard);
320 if (err != 0)
321 return err;
322 }
323 return pthread_rwlock_rdlock (&lock->rwlock);
324 }
325
326 int
327 glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
328 {
329 if (!lock->initialized)
330 {
331 int err;
332
333 err = pthread_mutex_lock (&lock->guard);
334 if (err != 0)
335 return err;
336 if (!lock->initialized)
337 {
338 err = glthread_rwlock_init_multithreaded (lock);
339 if (err != 0)
340 {
341 pthread_mutex_unlock (&lock->guard);
342 return err;
343 }
344 }
345 err = pthread_mutex_unlock (&lock->guard);
346 if (err != 0)
347 return err;
348 }
349 return pthread_rwlock_wrlock (&lock->rwlock);
350 }
351
352 int
353 glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
354 {
355 if (!lock->initialized)
356 return EINVAL;
357 return pthread_rwlock_unlock (&lock->rwlock);
358 }
359
360 int
361 glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
362 {
363 int err;
364
365 if (!lock->initialized)
366 return EINVAL;
367 err = pthread_rwlock_destroy (&lock->rwlock);
368 if (err != 0)
369 return err;
370 lock->initialized = 0;
371 return 0;
372 }
373
374 # endif
375
376 # else
377
378 int
379 glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
380 {
381 int err;
382
383 err = pthread_mutex_init (&lock->lock, NULL);
384 if (err != 0)
385 return err;
386 err = pthread_cond_init (&lock->waiting_readers, NULL);
387 if (err != 0)
388 return err;
389 err = pthread_cond_init (&lock->waiting_writers, NULL);
390 if (err != 0)
391 return err;
392 lock->waiting_writers_count = 0;
393 lock->runcount = 0;
394 return 0;
395 }
396
397 int
398 glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
399 {
400 int err;
401
402 err = pthread_mutex_lock (&lock->lock);
403 if (err != 0)
404 return err;
405
406
407
408
409 while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
410 {
411
412
413 err = pthread_cond_wait (&lock->waiting_readers, &lock->lock);
414 if (err != 0)
415 {
416 pthread_mutex_unlock (&lock->lock);
417 return err;
418 }
419 }
420 lock->runcount++;
421 return pthread_mutex_unlock (&lock->lock);
422 }
423
424 int
425 glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
426 {
427 int err;
428
429 err = pthread_mutex_lock (&lock->lock);
430 if (err != 0)
431 return err;
432
433 while (!(lock->runcount == 0))
434 {
435
436
437 lock->waiting_writers_count++;
438 err = pthread_cond_wait (&lock->waiting_writers, &lock->lock);
439 if (err != 0)
440 {
441 lock->waiting_writers_count--;
442 pthread_mutex_unlock (&lock->lock);
443 return err;
444 }
445 lock->waiting_writers_count--;
446 }
447 lock->runcount--;
448 return pthread_mutex_unlock (&lock->lock);
449 }
450
451 int
452 glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
453 {
454 int err;
455
456 err = pthread_mutex_lock (&lock->lock);
457 if (err != 0)
458 return err;
459 if (lock->runcount < 0)
460 {
461
462 if (!(lock->runcount == -1))
463 {
464 pthread_mutex_unlock (&lock->lock);
465 return EINVAL;
466 }
467 lock->runcount = 0;
468 }
469 else
470 {
471
472 if (!(lock->runcount > 0))
473 {
474 pthread_mutex_unlock (&lock->lock);
475 return EINVAL;
476 }
477 lock->runcount--;
478 }
479 if (lock->runcount == 0)
480 {
481
482
483 if (lock->waiting_writers_count > 0)
484 {
485
486 err = pthread_cond_signal (&lock->waiting_writers);
487 if (err != 0)
488 {
489 pthread_mutex_unlock (&lock->lock);
490 return err;
491 }
492 }
493 else
494 {
495
496 err = pthread_cond_broadcast (&lock->waiting_readers);
497 if (err != 0)
498 {
499 pthread_mutex_unlock (&lock->lock);
500 return err;
501 }
502 }
503 }
504 return pthread_mutex_unlock (&lock->lock);
505 }
506
507 int
508 glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
509 {
510 int err;
511
512 err = pthread_mutex_destroy (&lock->lock);
513 if (err != 0)
514 return err;
515 err = pthread_cond_destroy (&lock->waiting_readers);
516 if (err != 0)
517 return err;
518 err = pthread_cond_destroy (&lock->waiting_writers);
519 if (err != 0)
520 return err;
521 return 0;
522 }
523
524 # endif
525
526
527
528 # if HAVE_PTHREAD_MUTEX_RECURSIVE
529
530 # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
531
532 int
533 glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
534 {
535 pthread_mutexattr_t attributes;
536 int err;
537
538 err = pthread_mutexattr_init (&attributes);
539 if (err != 0)
540 return err;
541 err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
542 if (err != 0)
543 {
544 pthread_mutexattr_destroy (&attributes);
545 return err;
546 }
547 err = pthread_mutex_init (lock, &attributes);
548 if (err != 0)
549 {
550 pthread_mutexattr_destroy (&attributes);
551 return err;
552 }
553 err = pthread_mutexattr_destroy (&attributes);
554 if (err != 0)
555 return err;
556 return 0;
557 }
558
559 # else
560
561 int
562 glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
563 {
564 pthread_mutexattr_t attributes;
565 int err;
566
567 err = pthread_mutexattr_init (&attributes);
568 if (err != 0)
569 return err;
570 err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
571 if (err != 0)
572 {
573 pthread_mutexattr_destroy (&attributes);
574 return err;
575 }
576 err = pthread_mutex_init (&lock->recmutex, &attributes);
577 if (err != 0)
578 {
579 pthread_mutexattr_destroy (&attributes);
580 return err;
581 }
582 err = pthread_mutexattr_destroy (&attributes);
583 if (err != 0)
584 return err;
585 lock->initialized = 1;
586 return 0;
587 }
588
589 int
590 glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
591 {
592 if (!lock->initialized)
593 {
594 int err;
595
596 err = pthread_mutex_lock (&lock->guard);
597 if (err != 0)
598 return err;
599 if (!lock->initialized)
600 {
601 err = glthread_recursive_lock_init_multithreaded (lock);
602 if (err != 0)
603 {
604 pthread_mutex_unlock (&lock->guard);
605 return err;
606 }
607 }
608 err = pthread_mutex_unlock (&lock->guard);
609 if (err != 0)
610 return err;
611 }
612 return pthread_mutex_lock (&lock->recmutex);
613 }
614
615 int
616 glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
617 {
618 if (!lock->initialized)
619 return EINVAL;
620 return pthread_mutex_unlock (&lock->recmutex);
621 }
622
623 int
624 glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
625 {
626 int err;
627
628 if (!lock->initialized)
629 return EINVAL;
630 err = pthread_mutex_destroy (&lock->recmutex);
631 if (err != 0)
632 return err;
633 lock->initialized = 0;
634 return 0;
635 }
636
637 # endif
638
639 # else
640
641 int
642 glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
643 {
644 int err;
645
646 err = pthread_mutex_init (&lock->mutex, NULL);
647 if (err != 0)
648 return err;
649 lock->owner = (pthread_t) 0;
650 lock->depth = 0;
651 return 0;
652 }
653
654 int
655 glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
656 {
657 pthread_t self = pthread_self ();
658 if (lock->owner != self)
659 {
660 int err;
661
662 err = pthread_mutex_lock (&lock->mutex);
663 if (err != 0)
664 return err;
665 lock->owner = self;
666 }
667 if (++(lock->depth) == 0)
668 {
669 lock->depth--;
670 return EAGAIN;
671 }
672 return 0;
673 }
674
675 int
676 glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
677 {
678 if (lock->owner != pthread_self ())
679 return EPERM;
680 if (lock->depth == 0)
681 return EINVAL;
682 if (--(lock->depth) == 0)
683 {
684 lock->owner = (pthread_t) 0;
685 return pthread_mutex_unlock (&lock->mutex);
686 }
687 else
688 return 0;
689 }
690
691 int
692 glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
693 {
694 if (lock->owner != (pthread_t) 0)
695 return EBUSY;
696 return pthread_mutex_destroy (&lock->mutex);
697 }
698
699 # endif
700
701
702
703 static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
704
705 int
706 glthread_once_singlethreaded (pthread_once_t *once_control)
707 {
708
709
710 char *firstbyte = (char *)once_control;
711 if (*firstbyte == *(const char *)&fresh_once)
712 {
713
714 *firstbyte = ~ *(const char *)&fresh_once;
715 return 1;
716 }
717 else
718 return 0;
719 }
720
721 # if !(PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK)
722
723 int
724 glthread_once_multithreaded (pthread_once_t *once_control,
725 void (*init_function) (void))
726 {
727 int err = pthread_once (once_control, init_function);
728 if (err == ENOSYS)
729 {
730
731
732 if (glthread_once_singlethreaded (once_control))
733 init_function ();
734 return 0;
735 }
736 return err;
737 }
738
739 # endif
740
741 #endif
742
743
744
745 #if USE_WINDOWS_THREADS
746
747 #endif
748
749