vsync / spinlock / arraylock.h
Simple array-based queue lock.
Groups: Fair locks
The array lock has an array of flags, each slot is associated with a thread. If we have N threads then the array has N slots. Each slot represents a boolean flag indicating the associated thread’s permission to acquire the lock. The thread waits on its flag to become true to acquire the lock. The thread releases the lock, by giving away its permission to the next thread, i.e. sets its own flag to false and the flag of the one next in line to true.
Initially the first flag is set to true and the rest to false, and the tail holds the index of the first slot.
Example:
#include <vsync/spinlock/arraylock.h>
#include <vsync/common/assert.h>
#include <pthread.h>
#include <stdio.h>
#define N 12
#define EXPECTED_VAL N
#define NEXT_POWER_2 16U
arraylock_flag_t g_flags[NEXT_POWER_2];
arraylock_t g_lock;
vuint32_t g_x = 0;
vuint32_t g_y = 0;
void *
run(void *args)
{
vuint32_t slot = 0;
arraylock_acquire(&g_lock, &slot);
g_x++;
g_y++;
arraylock_release(&g_lock, slot);
(void)args;
return NULL;
}
int
main(void)
{
arraylock_init(&g_lock, g_flags, NEXT_POWER_2);
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;
}
References:
Maurice Herlihy, Nir Shavit - The Art of Multiprocessor Programming 7.5.1
Functions
| Function | Description |
|---|---|
| arraylock_init | Initializes the given lock object. |
| arraylock_acquire | Acquires the given lock. |
| arraylock_release | Releases the given lock. |
Function arraylock_init
static void arraylock_init(arraylock_t *lock, arraylock_flag_t *flags, const vuint32_t len)
Initializes the given lock object.
Parameters:
lock: address of arraylock_t object.flags: address of arraylock_flag_t object.len: next power of two greater or equal to the maximum number of threads. Length offlagsarray.
Note:
lenMUST BE A POWER OF TWO. This is required because we use a circular array and take advantage of unsigned integers “overflow”.
Function arraylock_acquire
static void arraylock_acquire(arraylock_t *lock, vuint32_t *slot)
Acquires the given lock.
Parameters:
lock: address of arraylock_t object.slot: output parameter. Stores the index of the slot associates with the calling thread.
Note: the same value returned in
slotmust be passed intact toarraylock_release.
Function arraylock_release
static void arraylock_release(arraylock_t *lock, vuint32_t slot)
Releases the given lock.
Parameters:
lock: address of arraylock_t object.slot: index of the slot associates with the calling thread.