#include <pthread.h>
#include "rwl.h"
void
rwl_init(rwl_t *rwlp)
{
pthread_mutex_init(&rwlp->m, pthread_mutexattr_default);
pthread_cond_init(&rwlp->readers_ok, pthread_condattr_default);
pthread_cond_init(&rwlp->writer_ok, pthread_condattr_default);
rwlp->rwlock = 0;
rwlp->waiting_writers = 0;
}
void
rwl_rdlock(rwl_t *rwlp)
{
pthread_mutex_lock(&rwlp->m);
while (rwlp->rwlock < 0 || rwlp->waiting_writers)
pthread_cond_wait(&rwlp->readers_ok, &rwlp->m);
rwlp->rwlock++;
pthread_mutex_unlock(&rwlp->m);
}
void
rwl_wrlock(rwl_t *rwlp)
{
pthread_mutex_lock(&rwlp->m);
while (rwlp->rwlock != 0) {
rwlp->waiting_writers++;
pthread_cond_wait(&rwlp->writer_ok, &rwlp->m);
rwlp->waiting_writers--;
}
rwlp->rwlock = -1;
pthread_mutex_unlock(&rwlp->m);
}
void
rwl_unlock(rwl_t *rwlp)
{
int ww, wr;
pthread_mutex_lock(&rwlp->m);
if (rwlp->rwlock < 0) rwlp->rwlock = 0;
else
rwlp->rwlock--;
ww = (rwlp->waiting_writers && rwlp->rwlock == 0);
wr = (rwlp->waiting_writers == 0);
pthread_mutex_unlock(&rwlp->m);
if (ww)
pthread_cond_signal(&rwlp->writer_ok);
else if (wr)
pthread_cond_broadcast(&rwlp->readers_ok);
}