vsync / spinlock / clhlock.h
List-based lock attributed to Craig, Landin and Hagersten.
Groups: Fair locks
Example:
#include <vsync/spinlock/clhlock.h>
#include <vsync/common/assert.h>
#include <pthread.h>
#include <stdio.h>
#define N 12
#define MAX_THREADS N
#define EXPECTED_VAL N
clhlock_t g_lock;
clh_node_t g_nodes[N];
vuint32_t g_x = 0;
vuint32_t g_y = 0;
void *
run(void *args)
{
vsize_t tid = (vsize_t)args;
clhlock_node_init(&g_nodes[tid]);
clhlock_acquire(&g_lock, &g_nodes[tid]);
g_x++;
g_y++;
clhlock_release(&g_lock, &g_nodes[tid]);
(void)args;
return NULL;
}
int
main(void)
{
pthread_t threads[N];
clhlock_init(&g_lock);
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
Functions
| Function | Description |
|---|---|
| clhlock_node_init | Initializes the given node. |
| clhlock_init | Initializes the given lock. |
| clhlock_acquire | Acquires the lock. |
| clhlock_release | Releases the lock. |
| clhlock_has_waiters | Returns whether there is a thread waiting to acquire the clhlock. |
Function clhlock_node_init
static void clhlock_node_init(clh_node_t *node)
Initializes the given node.
Parameters:
node: address of clh_node_t object.
Function clhlock_init
static void clhlock_init(clhlock_t *lock)
Initializes the given lock.
Parameters:
lock: address of clhlock_t object.
Function clhlock_acquire
static void clhlock_acquire(clhlock_t *lock, clh_node_t *node)
Acquires the lock.
Parameters:
lock: address of clhlock_t object.node: address of clh_node_t object associated with the calling thread.
Note:
nodehas to continue to exist even if the thread dies.
Function clhlock_release
static void clhlock_release(clhlock_t *lock, clh_node_t *node)
Releases the lock.
Parameters:
lock: address of clhlock_t object.node: address of clh_node_t object associated with the calling thread.
Note: It hijacks its predecessor’s queue node as its own.
Function clhlock_has_waiters
static vbool_t clhlock_has_waiters(clhlock_t *lock, clh_node_t *node)
Returns whether there is a thread waiting to acquire the clhlock.
This function should only be called by the current owner of the lock.
Parameters:
lock: address of clhlock_t object.node: address of clh_node_t object associated with the calling thread.
Returns: true if there are waiters.
Returns: false if there are no waiters.
Note: this function is not part of the standard lock API.