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