]> git.sur5r.net Git - openldap/blob - libraries/liblthread/rdwr.c
cebe318cdff827d2c18fd4ab749d5afb6d13c67c
[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 #include <stdlib.h>
21 #include <lthread.h>
22 #include <lthread_rdwr.h>
23
24 int pthread_rdwr_init_np(pthread_rdwr_t *rdwrp, pthread_rdwrattr_t *attrp)
25 {
26         rdwrp->readers_reading = 0;
27         rdwrp->writer_writing = 0;
28         pthread_mutex_init(&(rdwrp->mutex), NULL);
29         pthread_cond_init(&(rdwrp->lock_free), NULL);
30         return 0;
31 }
32
33 int pthread_rdwr_rlock_np(pthread_rdwr_t *rdwrp){
34         pthread_mutex_lock(&(rdwrp->mutex));
35         while(rdwrp->writer_writing) {
36                 pthread_cond_wait(&(rdwrp->lock_free), &(rdwrp->mutex));
37         }
38         rdwrp->readers_reading++;
39         pthread_mutex_unlock(&(rdwrp->mutex));
40         return 0;
41 }
42
43 int pthread_rdwr_runlock_np(pthread_rdwr_t *rdwrp)
44 {
45         pthread_mutex_lock(&(rdwrp->mutex));
46         if (rdwrp->readers_reading == 0) {
47                 pthread_mutex_unlock(&(rdwrp->mutex));
48                 return -1;
49         }
50         else {
51                 rdwrp->readers_reading--;
52                 if (rdwrp->readers_reading == 0) {
53                         pthread_cond_signal(&(rdwrp->lock_free));
54                 }
55                 pthread_mutex_unlock(&(rdwrp->mutex));
56                 return 0;
57         }
58 }
59
60 int pthread_rdwr_wlock_np(pthread_rdwr_t *rdwrp)
61 {
62         pthread_mutex_lock(&(rdwrp->mutex));
63         while(rdwrp->writer_writing || rdwrp->readers_reading) {
64                 pthread_cond_wait(&(rdwrp->lock_free), &(rdwrp->mutex));
65         }
66         rdwrp->writer_writing++;
67         pthread_mutex_unlock(&(rdwrp->mutex));
68         return 0;
69 }
70
71 int pthread_rdwr_wunlock_np(pthread_rdwr_t *rdwrp)
72 {
73         pthread_mutex_lock(&(rdwrp->mutex));
74         if (rdwrp->writer_writing == 0) {
75                 pthread_mutex_unlock(&(rdwrp->mutex));
76                 return -1;
77         }
78         else {
79                 rdwrp->writer_writing = 0;
80                 pthread_cond_broadcast(&(rdwrp->lock_free));
81                 pthread_mutex_unlock(&(rdwrp->mutex));
82                 return 0;
83         }
84 }
85
86 #ifdef LDAP_DEBUG
87
88 /* just for testing, 
89  * return 0 if false, suitable for assert(pthread_rdwr_Xchk(rdwr))
90  * 
91  * Currently they don't check if the calling thread is the one 
92  * that has the lock, just that there is a reader or writer.
93  *
94  * Basically sufficent for testing that places that should have
95  * a lock are caught.
96  */
97
98 int pthread_rdwr_rchk_np(pthread_rdwr_t *rdwrp)
99 {
100         return(rdwrp->readers_reading!=0);
101 }
102
103 int pthread_rdwr_wchk_np(pthread_rdwr_t *rdwrp)
104 {
105         return(rdwrp->writer_writing!=0);
106 }
107 int pthread_rdwr_rwchk_np(pthread_rdwr_t *rdwrp)
108 {
109         return(pthread_rdwr_rchk_np(rdwrp) || pthread_rdwr_wchk_np(rdwrp));
110 }
111
112 #endif /* LDAP_DEBUG */