vsync / spinlock / rec_mcslock.h
Recursive MCS lock implementation using recursive.h.
Groups: Fair locks
rec_mcslock is a MCS lock that supports recursion, i.e., is reentrant.
see mcslock.h
Example:
#include <vsync/spinlock/rec_mcslock.h>
#include <vsync/common/assert.h>
#include <pthread.h>
#include <stdio.h>
#define N 12
#define EXPECTED_VAL N
rec_mcslock_t g_lock = REC_MCSLOCK_INIT();
mcs_node_t g_nodes[N];
vuint32_t g_x = 0;
vuint32_t g_y = 0;
void *
run(void *args)
{
vuint32_t tid = (vuint32_t)(vsize_t)args;
mcs_node_t *node = &g_nodes[tid];
// can be acquired multiple times without causing dead-lock
rec_mcslock_acquire(&g_lock, tid, node);
rec_mcslock_acquire(&g_lock, tid, node);
g_x++;
g_y++;
rec_mcslock_release(&g_lock, node);
rec_mcslock_release(&g_lock, node);
(void)args;
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 |
|---|---|
| REC_MCSLOCK_INIT | Initializer of rec_mcslock. |
Macro REC_MCSLOCK_INIT
REC_MCSLOCK_INIT()
Initializer of rec_mcslock.
Functions
| Function | Description |
|---|---|
| rec_mcslock_init | Initializes the recursive MCS lock. |
| rec_mcslock_acquire | Acquires the recursive MCS lock. |
| rec_mcslock_release | Releases the recursive MCS lock. |
| rec_mcslock_tryacquire | Tries to acquire the recursive mcslock. |
Function rec_mcslock_init
static void rec_mcslock_init(struct rec_mcslock_s *l)
Initializes the recursive MCS lock.
Parameters:
l: address of rec_mcslock_t object.
Note: alternatively use
REC_MCSLOCK_INIT.
Function rec_mcslock_acquire
static void rec_mcslock_acquire(struct rec_mcslock_s *l, vuint32_t id, mcs_node_t *ctx)
Acquires the recursive MCS lock.
This function can be called multiple times by the same thread, consecutively.
Parameters:
l: address of rec_mcslock_t object.id: thread ID or core IDctx: address of rec_mcslock_t object associated with the caller thread/core.
Function rec_mcslock_release
static void rec_mcslock_release(struct rec_mcslock_s *l, mcs_node_t *ctx)
Releases the recursive MCS lock.
To fully release the lock, this function should be called the same number of times as the acquire was consecutively called by thread that currently owns the lock.
Parameters:
l: address of rec_mcslock_t object.ctx: address of rec_mcslock_t object associated with the caller thread/core.
Function rec_mcslock_tryacquire
static vbool_t rec_mcslock_tryacquire(struct rec_mcslock_s *l, vuint32_t id, mcs_node_t *ctx)
Tries to acquire the recursive mcslock.
This can be called multiple times by the same thread, consecutively.
Parameters:
l: address of rec_mcslock_t object.id: thread ID or core ID.
Returns: true, if lock is acquired successfully.
Returns: false, if failed to acquire the lock.