xref: /minix3/minix/lib/libmthread/rwlock.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 #include <minix/mthread.h>
2 #include "global.h"
3 
4 /*===========================================================================*
5  *				mthread_rwlock_init			     *
6  *===========================================================================*/
mthread_rwlock_init(rwlock)7 int mthread_rwlock_init(rwlock)
8 mthread_rwlock_t *rwlock; /* The rwlock to be initialized */
9 {
10   /* Initialize a readers/writer lock. */
11   int r;
12 
13   if (!rwlock)
14 	return EINVAL;
15 
16   rwlock->writer = NO_THREAD;
17   rwlock->readers = 0;
18 
19   r = mthread_mutex_init(&rwlock->queue, NULL);
20   if (r != 0)
21 	return r;
22 
23   r = mthread_event_init(&rwlock->drain);
24   if (r != 0)
25 	mthread_mutex_destroy(&rwlock->queue);
26 
27   return r;
28 }
29 
30 /*===========================================================================*
31  *				mthread_rwlock_destroy			     *
32  *===========================================================================*/
mthread_rwlock_destroy(rwlock)33 int mthread_rwlock_destroy(rwlock)
34 mthread_rwlock_t *rwlock; /* The rwlock to be destroyed */
35 {
36   /* Destroy a readers/writer lock. */
37   int r;
38 
39   if (!rwlock)
40 	return EINVAL;
41 
42   assert(rwlock->writer == NO_THREAD);
43   assert(rwlock->readers == 0);
44 
45   r = mthread_event_destroy(&rwlock->drain);
46   if (r != 0)
47 	return r;
48 
49   return mthread_mutex_destroy(&rwlock->queue);
50 }
51 
52 /*===========================================================================*
53  *				mthread_rwlock_rdlock			     *
54  *===========================================================================*/
mthread_rwlock_rdlock(rwlock)55 int mthread_rwlock_rdlock(rwlock)
56 mthread_rwlock_t *rwlock; /* The rwlock to be read locked */
57 {
58   /* Acquire a reader lock. */
59   int r;
60 
61   if (!rwlock)
62 	return EINVAL;
63 
64   r = mthread_mutex_lock(&rwlock->queue);
65   if (r != 0)
66 	return r;
67 
68   r = mthread_mutex_unlock(&rwlock->queue);
69   if (r != 0)
70 	return r;
71 
72   rwlock->readers++;
73 
74   return 0;
75 }
76 
77 /*===========================================================================*
78  *				mthread_rwlock_wrlock			     *
79  *===========================================================================*/
mthread_rwlock_wrlock(rwlock)80 int mthread_rwlock_wrlock(rwlock)
81 mthread_rwlock_t *rwlock; /* The rwlock to be write locked */
82 {
83   /* Acquire a writer lock. */
84   int r;
85 
86   if (!rwlock)
87 	  return EINVAL;
88 
89   r = mthread_mutex_lock(&rwlock->queue);
90   if (r != 0)
91 	return r;
92 
93   rwlock->writer = current_thread;
94 
95   if (rwlock->readers > 0)
96 	r = mthread_event_wait(&rwlock->drain);
97 
98   if (r == 0)
99 	assert(rwlock->readers == 0);
100 
101   return r;
102 }
103 
104 /*===========================================================================*
105  *				mthread_rwlock_unlock				*
106  *===========================================================================*/
mthread_rwlock_unlock(rwlock)107 int mthread_rwlock_unlock(rwlock)
108 mthread_rwlock_t *rwlock; /* The rwlock to be unlocked */
109 {
110   /* Release a lock. */
111   int r;
112 
113   r = 0;
114   if (!rwlock)
115 	  return EINVAL;
116 
117   if (rwlock->writer == current_thread) {
118 	rwlock->writer = NO_THREAD;
119 	r = mthread_mutex_unlock(&rwlock->queue);
120   } else {
121 	assert(rwlock->readers > 0);
122 
123 	rwlock->readers--;
124 
125 	if (rwlock->readers == 0 && rwlock->writer != NO_THREAD)
126 		r = mthread_event_fire(&rwlock->drain);
127   }
128 
129   return r;
130 }
131 
132 /* pthread compatibility layer. */
133 __weak_alias(pthread_rwlock_destroy, mthread_rwlock_destroy)
134 __weak_alias(pthread_rwlock_rdlock, mthread_rwlock_rdlock)
135 __weak_alias(pthread_rwlock_wrlock, mthread_rwlock_wrlock)
136 __weak_alias(pthread_rwlock_unlock, mthread_rwlock_unlock)
137 
138