/* BeginSourceFile rw_locks.c */ #include #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; } /* * Acquire a read lock. Multiple readers can go if there are no * writers. */ 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); } /* * Acquire a write lock. Only a single writer can proceed. */ 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); } /* * Unlock the read/write lock. */ void rwl_unlock(rwl_t *rwlp) { int ww, wr; pthread_mutex_lock(&rwlp->m); if (rwlp->rwlock < 0) /* rwlock < 0 if locked for writing */ rwlp->rwlock = 0; else rwlp->rwlock--; /* * Keep flags that show if there are waiting readers or writers so * that we can wake them up outside the monitor lock. */ ww = (rwlp->waiting_writers && rwlp->rwlock == 0); wr = (rwlp->waiting_writers == 0); pthread_mutex_unlock(&rwlp->m); /* wakeup a waiting writer first. Otherwise wakeup all readers */ if (ww) pthread_cond_signal(&rwlp->writer_ok); else if (wr) pthread_cond_broadcast(&rwlp->readers_ok); } /* EndSourceFile */