mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-18 02:50:09 +00:00
110 lines
2.5 KiB
Plaintext
110 lines
2.5 KiB
Plaintext
|
Reader Writer Locks pseudocode
|
||
|
==============================
|
||
|
|
||
|
pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
|
||
|
pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
|
||
|
pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
|
||
|
|
||
|
struct pthread_rwlock_t {
|
||
|
|
||
|
unsigned int lock:
|
||
|
- internal mutex
|
||
|
|
||
|
unsigned int writers_preferred;
|
||
|
- locking mode: 0 recursive, readers preferred
|
||
|
1 nonrecursive, writers preferred
|
||
|
|
||
|
unsigned int readers;
|
||
|
- number of read-only references various threads have
|
||
|
|
||
|
pthread_t writer;
|
||
|
- descriptor of the writer or 0
|
||
|
|
||
|
unsigned int readers_wakeup;
|
||
|
- 'all readers should wake up' futex.
|
||
|
|
||
|
unsigned int writer_wakeup;
|
||
|
- 'one writer should wake up' futex.
|
||
|
|
||
|
unsigned int nr_readers_queued;
|
||
|
- number of readers queued up.
|
||
|
|
||
|
unsigned int nr_writers_queued;
|
||
|
- number of writers queued up.
|
||
|
}
|
||
|
|
||
|
pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
|
||
|
{
|
||
|
lll_lock(rwlock->lock);
|
||
|
for (;;) {
|
||
|
if (!rwlock->writer && (!rwlock->nr_writers_queued ||
|
||
|
!rwlock->writers_preferred))
|
||
|
break;
|
||
|
|
||
|
rwlock->nr_readers_queued++;
|
||
|
lll_unlock(rwlock->lock);
|
||
|
|
||
|
futex_wait(&rwlock->readers_wakeup, 0)
|
||
|
|
||
|
lll_lock(rwlock->lock);
|
||
|
if (!--rwlock->nr_readers_queued)
|
||
|
rwlock->readers_wakeup = 0;
|
||
|
}
|
||
|
rwlock->readers++;
|
||
|
lll_unlock(rwlock->lock);
|
||
|
}
|
||
|
|
||
|
pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
|
||
|
{
|
||
|
int result = EBUSY;
|
||
|
lll_lock(rwlock->lock);
|
||
|
if (!rwlock->writer && (!rwlock->nr_writers_queued ||
|
||
|
!rwlock->writers_preferred))
|
||
|
rwlock->readers++;
|
||
|
lll_unlock(rwlock->lock);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
|
||
|
{
|
||
|
lll_lock(rwlock->lock);
|
||
|
for (;;) {
|
||
|
if (!rwlock->writer && !rwlock->readers)
|
||
|
break;
|
||
|
|
||
|
rwlock->nr_writers_queued++;
|
||
|
lll_unlock(rwlock->lock);
|
||
|
|
||
|
futex_wait(&rwlock->writer_wakeup, 0);
|
||
|
|
||
|
lll_lock(rwlock->lock);
|
||
|
rwlock->nr_writers_queued--;
|
||
|
rwlock->writer_wakeup = 0;
|
||
|
}
|
||
|
rwlock->writer = pthread_self();
|
||
|
lll_unlock(rwlock->lock);
|
||
|
}
|
||
|
|
||
|
pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
|
||
|
{
|
||
|
lll_lock(rwlock->lock);
|
||
|
|
||
|
if (rwlock->writer)
|
||
|
rwlock->writer = 0;
|
||
|
else
|
||
|
rwlock->readers--;
|
||
|
|
||
|
if (!rwlock->readers) {
|
||
|
if (rwlock->nr_writers_queued) {
|
||
|
rwlock->writer_wakeup = 1;
|
||
|
futex_wake(&rwlock->writer_wakeup, 1);
|
||
|
} else
|
||
|
if (rwlock->nr_readers_queued) {
|
||
|
rwlock->readers_wakeup = 1;
|
||
|
futex_wake(&rwlock->readers_wakeup, MAX_INT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lll_unlock(rwlock->lock);
|
||
|
}
|