vsync / spinlock / rwlock.h
Write-preferring rwlock based on semaphore and an atomic vbool_t.
see vsync/spinlock/semaphore.h
When acquiring a read lock, wait for writers and then reserve one resource. When acquiring a write lock, lock writer bit and reserve all N resources.
Algorithm:
write_acquire:
await (wb = 0)
wb = 1
await (resources = N)
resources = 0
write_release:
wb = 0
resources = N
read_acquire:
await (wb = 0)
await (resources > 0)
resources--
read_release:
resources++
Example:
#include <vsync/spinlock/rwlock.h>
#include <vsync/common/assert.h>
#include <pthread.h>
#include <stdio.h>
#define N 24
#define EXPECTED_VAL (N / 2)
rwlock_t g_lock = RWLOCK_INIT();
vuint32_t g_x = 0;
vuint32_t g_y = 0;
void
writer(void)
{
rwlock_write_acquire(&g_lock);
g_x++;
g_y++;
rwlock_write_release(&g_lock);
}
void
reader(void)
{
vuint32_t a = 0;
vuint32_t b = 0;
rwlock_read_acquire(&g_lock);
a = g_x;
b = g_y;
rwlock_read_release(&g_lock);
/* what we read must be consistent */
ASSERT(a == b);
}
void *
run(void *args)
{
vsize_t tid = (vsize_t)args;
if (tid % 2 == 0) {
reader();
} else {
writer();
}
return NULL;
}
int
main(void)
{
pthread_t threads[N];
for (vsize_t i = 0; i < N; i++) {
pthread_create(&threads[i], NULL, run, (void *)i);
}
for (vsize_t i = 0; i < N; i++) {
pthread_join(threads[i], NULL);
}
ASSERT(g_x == EXPECTED_VAL);
ASSERT(g_x == g_y);
printf("Final value %u\n", g_x);
return 0;
}
Macros
| Macro | Description |
|---|---|
| RWLOCK_INITN | Initializer of rwlock_t. |
| RWLOCK_INIT | Initializer of rwlock_t with the default number of resources. |
Macro RWLOCK_INITN
RWLOCK_INITN(N)
Initializer of rwlock_t.
Macro RWLOCK_INIT
RWLOCK_INIT()
Initializer of rwlock_t with the default number of resources.
Functions
| Function | Description |
|---|---|
| rwlock_init | Initializes the rwlock. |
| rwlock_write_acquire | Acquires the write lock. |
| rwlock_write_tryacquire | Tries to acquire the write lock. |
| rwlock_write_release | Releases the write lock. |
| rwlock_read_acquire | Acquires the read lock. |
| rwlock_read_tryacquire | Tries to acquire the read lock. |
| rwlock_read_release | Releases the read lock. |
| rwlock_acquired_by_writer | Returns true if a writer has acquired the lock, or waiting on the readers to release it. |
| rwlock_acquired_by_readers | Returns true if the lock is acquired by readers. |
Function rwlock_init
static void rwlock_init(rwlock_t *l)
Initializes the rwlock.
Parameters:
l: address of rwlock_t object.
Note: alternatively use
RWLOCK_INIT.
Function rwlock_write_acquire
static void rwlock_write_acquire(rwlock_t *l)
Acquires the write lock.
Parameters:
l: address of rwlock_t object.
Function rwlock_write_tryacquire
static vbool_t rwlock_write_tryacquire(rwlock_t *l)
Tries to acquire the write lock.
Parameters:
l: address of rwlock_t object.
Returns: true, if lock is acquired successfully.
Returns: false, if failed to acquire the lock.
Function rwlock_write_release
static void rwlock_write_release(rwlock_t *l)
Releases the write lock.
Parameters:
l: address of rwlock_t object.
Function rwlock_read_acquire
static void rwlock_read_acquire(rwlock_t *l)
Acquires the read lock.
Parameters:
l: address of rwlock_t object.
Function rwlock_read_tryacquire
static vbool_t rwlock_read_tryacquire(rwlock_t *l)
Tries to acquire the read lock.
Parameters:
l: address of rwlock_t object.
Returns: true, if lock is acquired successfully.
Returns: false, if failed to acquire the lock.
Function rwlock_read_release
static void rwlock_read_release(rwlock_t *l)
Releases the read lock.
Parameters:
l: address of rwlock_t object.
Function rwlock_acquired_by_writer
static vbool_t rwlock_acquired_by_writer(rwlock_t *l)
Returns true if a writer has acquired the lock, or waiting on the readers to release it.
Parameters:
l: address of rwlock_t object.
Returns: true a writer has acquired or waiting on readers to release the lock.
Returns: false the lock is not acquired by a writer.
Function rwlock_acquired_by_readers
static vbool_t rwlock_acquired_by_readers(rwlock_t *l)
Returns true if the lock is acquired by readers.
Parameters:
l: address of rwlock_t object.
Returns: true if the lock is acquired by readers.
Returns: false if the lock is not acquired by readers.