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