Implements a simple many readers and single writer lock for threads of a single process.
ReadWriteLock | Implements a simple many readers and single writer lock for threads of a single process. |
Copyright | This program is free software. |
Files | |
C-kern/ | Header file ReadWriteLock. |
C-kern/ | Implementation file ReadWriteLock Linuximpl. |
Types | |
struct rwlock_t | Export rwlock_t into global namespace. |
Functions | |
test | |
unittest_platform_sync_rwlock | Test rwlock_t functionality. |
rwlock_t | Protect a data structure from access of threads of a single process. |
readers | Points to last entry in list of waiting readers. |
writers | Points to last entry in list of waiting writers. |
writer | The thread which holds <entrylock>. |
nrofreader | The number of readers currently reading the protected data structure. |
lockflag | Lock flag used to protect access to data members. |
lifetime | |
rwlock_FREE | Static initializer. |
rwlock_INIT | Static initializer. |
init_rwlock | Initializes data members. |
free_rwlock | Frees mutex. |
query | |
nrofreader_rwlock | Returns the number of readers holding the lock. |
iswriter_rwlock | Returns true if there is a single writer holding the lock. |
synchronize | |
lockreader_rwlock | Acquire <entrylock>, increment nrofreader and release <entrylock>. |
lockwriter_rwlock | Acquire <entrylock>, sets writer to seld and wait until nrofreader == 0. |
unlockreader_rwlock | Acquire <exitlock>, decrement nrofreader and return. |
unlockwriter_rwlock | Sets writer to 0 and unlocks <entrylock>. |
safe-synchronize | |
slockreader_rwlock | Asserts that lockreader_rwlock has no error. |
slockwriter_rwlock | Asserts that lockwriter_rwlock has no error. |
sunlockreader_rwlock | Asserts that unlockreader_rwlock has no error. |
sunlockwriter_rwlock | Asserts that unlockwriter_rwlock has no error. |
inline implementation | |
Macros | |
init_rwlock | Implements rwlock_t.init_rwlock. |
slockreader_rwlock | Implements rwlock_t.slockreader_rwlock. |
slockwriter_rwlock | Implements rwlock_t.slockwriter_rwlock. |
sunlockreader_rwlock | Implements rwlock_t.sunlockreader_rwlock. |
sunlockwriter_rwlock | Implements rwlock_t.sunlockwriter_rwlock. |
This program is free software. You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
© 2013 Jörg Seebohn
Header file ReadWriteLock.
Implementation file ReadWriteLock Linuximpl.
typedef struct rwlock_t rwlock_t
Export rwlock_t into global namespace.
test | |
unittest_platform_sync_rwlock | Test rwlock_t functionality. |
int unittest_platform_sync_rwlock( void )
Test rwlock_t functionality.
struct rwlock_t
Protect a data structure from access of threads of a single process. Either a single writer is allowed to enter the protected area or one or more readers are allowed to enter. As long as no writer tries to acquire this lock no reader has to wait. If a writer tries to acquire this type of lock it has to wait until all readers have released the lock. A writer inserts itself in waiting list writers. If at least a single writer waits all calls to lockreader_rwlock inserts the reader into the the readers waiting list.
The last reader which calls unlockreader_rwlock resumes a waiting writer.
During this time all other parties (reader or writer) have to wait until all readers and the single writer have released the lock.
A call unlockwriter_rwlock wakes up first any waiting reader.
So a writer releasing the lock wakes up all readers. The last reader releasing the lock wakes up the first waiting writer.
The implementation an atomic lockflag. Every call to lockreader_rwlock, lockwriter_rwlock, unlockreader_rwlock and unlockwriter_rwlock acquires this lock. At the end they release the lock.
If during operation of unlockreader_rwlock or unlockwriter_rwlock a writer or reader is woken up the woken up thread acquires lockflag and releases it. This ensures that any data written by the caller to unlockwriter_rwlock and any data written within the functions unlockreader_rwlock or unlockwriter_rwlock are known to the woken up thread.
readers | Points to last entry in list of waiting readers. |
writers | Points to last entry in list of waiting writers. |
writer | The thread which holds <entrylock>. |
nrofreader | The number of readers currently reading the protected data structure. |
lockflag | Lock flag used to protect access to data members. |
lifetime | |
rwlock_FREE | Static initializer. |
rwlock_INIT | Static initializer. |
init_rwlock | Initializes data members. |
free_rwlock | Frees mutex. |
query | |
nrofreader_rwlock | Returns the number of readers holding the lock. |
iswriter_rwlock | Returns true if there is a single writer holding the lock. |
synchronize | |
lockreader_rwlock | Acquire <entrylock>, increment nrofreader and release <entrylock>. |
lockwriter_rwlock | Acquire <entrylock>, sets writer to seld and wait until nrofreader == 0. |
unlockreader_rwlock | Acquire <exitlock>, decrement nrofreader and return. |
unlockwriter_rwlock | Sets writer to 0 and unlocks <entrylock>. |
safe-synchronize | |
slockreader_rwlock | Asserts that lockreader_rwlock has no error. |
slockwriter_rwlock | Asserts that lockwriter_rwlock has no error. |
sunlockreader_rwlock | Asserts that unlockreader_rwlock has no error. |
sunlockwriter_rwlock | Asserts that unlockwriter_rwlock has no error. |
struct thread_t * writer
The thread which holds <entrylock>. If nrofreader is greater 0 it is in suspended state.
void init_rwlock( /*out*/rwlock_t * rwlock )
Initializes data members. The same as assigning rwlock_INIT.
int lockreader_rwlock( rwlock_t * rwlock )
Acquire <entrylock>, increment nrofreader and release <entrylock>. After return nrofreader is > 0 and means a region is protected for reading. A return value of EOVERFLOW indicates that nrofreader == UINT32_MAX and no more reader is allowed to enter.
int lockwriter_rwlock( rwlock_t * rwlock )
Acquire <entrylock>, sets writer to seld and wait until nrofreader == 0. If nrofreader > 0 the calling thread is suspended and the last reader leaving the protected region with unlockreader_rwlock resumes the waiting writer.
After the writer has been resumed it acquires <exitlock> to ensure that it read a current nrofreader and releases <exitlock>. This also prevents a race condition if a spurious resume (suprious signal) wakes up the writer but the reader has not send the resume to the waiter. If nrofreader equals 0 the call returns else the caller is suspend again.
int unlockreader_rwlock( rwlock_t * rwlock )
Acquire <exitlock>, decrement nrofreader and return. Call this function only after calling lockreader_rwlock. If you forget one call nrofreader is wrong and no writer or other reader is allowed to enter.
int unlockwriter_rwlock( rwlock_t * rwlock )
Sets writer to 0 and unlocks <entrylock>. Other writers or readers are allowed to enter (entrylock is unlocked). Call this function only after calling lockwriter_rwlock else EPERM is returned and writer is not changed.
void slockreader_rwlock( rwlock_t * rwlock )
Asserts that lockreader_rwlock has no error.
void slockwriter_rwlock( rwlock_t * rwlock )
Asserts that lockwriter_rwlock has no error.
void sunlockreader_rwlock( rwlock_t * rwlock )
Asserts that unlockreader_rwlock has no error.
void sunlockwriter_rwlock( rwlock_t * rwlock )
Asserts that unlockwriter_rwlock has no error.
Macros | |
init_rwlock | Implements rwlock_t.init_rwlock. |
slockreader_rwlock | Implements rwlock_t.slockreader_rwlock. |
slockwriter_rwlock | Implements rwlock_t.slockwriter_rwlock. |
sunlockreader_rwlock | Implements rwlock_t.sunlockreader_rwlock. |
sunlockwriter_rwlock | Implements rwlock_t.sunlockwriter_rwlock. |
#define init_rwlock( rwlock ) ((void)(*(rwlock) = (rwlock_t) rwlock_INIT))
Implements rwlock_t.init_rwlock.
#define slockreader_rwlock( rwlock ) (assert(!lockreader_rwlock(rwlock)))
Implements rwlock_t.slockreader_rwlock.
#define slockwriter_rwlock( rwlock ) (assert(!lockwriter_rwlock(rwlock)))
Implements rwlock_t.slockwriter_rwlock.
#define sunlockreader_rwlock( rwlock ) (assert(!unlockreader_rwlock(rwlock)))
Implements rwlock_t.sunlockreader_rwlock.
#define sunlockwriter_rwlock( rwlock ) (assert(!unlockwriter_rwlock(rwlock)))
Implements rwlock_t.sunlockwriter_rwlock.
Export rwlock_t into global namespace.
typedef struct rwlock_t rwlock_t
Protect a data structure from access of threads of a single process.
struct rwlock_t
Test rwlock_t functionality.
int unittest_platform_sync_rwlock( void )
Points to last entry in list of waiting readers.
struct { struct slist_node_t * last ; } readers
Points to last entry in list of waiting writers.
struct { struct slist_node_t * last ; } writers
The thread which holds entrylock.
struct thread_t * writer
The number of readers currently reading the protected data structure.
uint32_t nrofreader
Lock flag used to protect access to data members.
uint8_t lockflag
Static initializer.
#define rwlock_FREE { { 0 } , { 0 }, 0, 0, 0 }
Static initializer.
#define rwlock_INIT { { 0 } , { 0 }, 0, 0, 0 }
Initializes data members.
void init_rwlock( /*out*/rwlock_t * rwlock )
Frees mutex.
int free_rwlock( rwlock_t * rwlock )
Returns the number of readers holding the lock.
uint32_t nrofreader_rwlock( rwlock_t * rwlock )
Returns true if there is a single writer holding the lock.
bool iswriter_rwlock( rwlock_t * rwlock )
Acquire entrylock, increment nrofreader and release entrylock.
int lockreader_rwlock( rwlock_t * rwlock )
Acquire entrylock, sets writer to seld and wait until nrofreader == 0.
int lockwriter_rwlock( rwlock_t * rwlock )
Acquire exitlock, decrement nrofreader and return.
int unlockreader_rwlock( rwlock_t * rwlock )
Sets writer to 0 and unlocks entrylock.
int unlockwriter_rwlock( rwlock_t * rwlock )
Asserts that lockreader_rwlock has no error.
void slockreader_rwlock( rwlock_t * rwlock )
Asserts that lockwriter_rwlock has no error.
void slockwriter_rwlock( rwlock_t * rwlock )
Asserts that unlockreader_rwlock has no error.
void sunlockreader_rwlock( rwlock_t * rwlock )
Asserts that unlockwriter_rwlock has no error.
void sunlockwriter_rwlock( rwlock_t * rwlock )
Implements rwlock_t.init_rwlock.
#define init_rwlock( rwlock ) ((void)(*(rwlock) = (rwlock_t) rwlock_INIT))
Implements rwlock_t.slockreader_rwlock.
#define slockreader_rwlock( rwlock ) (assert(!lockreader_rwlock(rwlock)))
Implements rwlock_t.slockwriter_rwlock.
#define slockwriter_rwlock( rwlock ) (assert(!lockwriter_rwlock(rwlock)))
Implements rwlock_t.sunlockreader_rwlock.
#define sunlockreader_rwlock( rwlock ) (assert(!unlockreader_rwlock(rwlock)))
Implements rwlock_t.sunlockwriter_rwlock.
#define sunlockwriter_rwlock( rwlock ) (assert(!unlockwriter_rwlock(rwlock)))