]> git.sur5r.net Git - openldap/blob - libraries/liblthread/rdwr.c
Fix rwlock pthread draft4 compatibility.
[openldap] / libraries / liblthread / rdwr.c
1 /*
2 ** This basic implementation of Reader/Writer locks does not
3 ** protect writers from starvation.  That is, if a writer is
4 ** currently waiting on a reader, any new reader will get
5 ** the lock before the writer.
6 */
7
8 /********************************************************
9  * An example source module to accompany...
10  *
11  * "Using POSIX Threads: Programming with Pthreads"
12  *               by Brad nichols, Dick Buttlar, Jackie Farrell
13  *               O'Reilly & Associates, Inc.
14  *
15  ********************************************************
16  * rdwr.c --
17  * 
18  * Library of functions implementing reader/writer locks
19  */
20
21 #include <portable.h>
22
23 #include <stdlib.h>
24 #include <lthread.h>
25 #include <lthread_rdwr.h>
26
27 int pthread_rdwr_init_np(pthread_rdwr_t *rdwrp, pthread_rdwrattr_t *attrp)
28 {
29         rdwrp->readers_reading = 0;
30         rdwrp->writer_writing = 0;
31         pthread_mutex_init(&(rdwrp->mutex), pthread_mutexattr_default);
32         pthread_cond_init(&(rdwrp->lock_free), pthread_condattr_default);
33         return 0;
34 }
35
36 int pthread_rdwr_rlock_np(pthread_rdwr_t *rdwrp){
37         pthread_mutex_lock(&(rdwrp->mutex));
38         while(rdwrp->writer_writing) {
39                 pthread_cond_wait(&(rdwrp->lock_free), &(rdwrp->mutex));
40         }
41         rdwrp->readers_reading++;
42         pthread_mutex_unlock(&(rdwrp->mutex));
43         return 0;
44 }
45
46 int pthread_rdwr_runlock_np(pthread_rdwr_t *rdwrp)
47 {
48         pthread_mutex_lock(&(rdwrp->mutex));
49         if (rdwrp->readers_reading == 0) {
50                 pthread_mutex_unlock(&(rdwrp->mutex));
51                 return -1;
52         }
53         else {
54                 rdwrp->readers_reading--;
55                 if (rdwrp->readers_reading == 0) {
56                         pthread_cond_signal(&(rdwrp->lock_free));
57                 }
58                 pthread_mutex_unlock(&(rdwrp->mutex));
59                 return 0;
60         }
61 }
62
63 int pthread_rdwr_wlock_np(pthread_rdwr_t *rdwrp)
64 {
65         pthread_mutex_lock(&(rdwrp->mutex));
66         while(rdwrp->writer_writing || rdwrp->readers_reading) {
67                 pthread_cond_wait(&(rdwrp->lock_free), &(rdwrp->mutex));
68         }
69         rdwrp->writer_writing++;
70         pthread_mutex_unlock(&(rdwrp->mutex));
71         return 0;
72 }
73
74 int pthread_rdwr_wunlock_np(pthread_rdwr_t *rdwrp)
75 {
76         pthread_mutex_lock(&(rdwrp->mutex));
77         if (rdwrp->writer_writing == 0) {
78                 pthread_mutex_unlock(&(rdwrp->mutex));
79                 return -1;
80         }
81         else {
82                 rdwrp->writer_writing = 0;
83                 pthread_cond_broadcast(&(rdwrp->lock_free));
84                 pthread_mutex_unlock(&(rdwrp->mutex));
85                 return 0;
86         }
87 }
88
89 #ifdef LDAP_DEBUG
90
91 /* just for testing, 
92  * return 0 if false, suitable for assert(pthread_rdwr_Xchk(rdwr))
93  * 
94  * Currently they don't check if the calling thread is the one 
95  * that has the lock, just that there is a reader or writer.
96  *
97  * Basically sufficent for testing that places that should have
98  * a lock are caught.
99  */
100
101 int pthread_rdwr_rchk_np(pthread_rdwr_t *rdwrp)
102 {
103         return(rdwrp->readers_reading!=0);
104 }
105
106 int pthread_rdwr_wchk_np(pthread_rdwr_t *rdwrp)
107 {
108         return(rdwrp->writer_writing!=0);
109 }
110 int pthread_rdwr_rwchk_np(pthread_rdwr_t *rdwrp)
111 {
112         return(pthread_rdwr_rchk_np(rdwrp) || pthread_rdwr_wchk_np(rdwrp));
113 }
114
115 #endif /* LDAP_DEBUG */