xtc_lwlock(3)
---xtc_lwlock(3)
lightweight lock with shared / exclusive modes
| XTC_LWLOCK(3) | Library Functions Manual | XTC_LWLOCK(3) |
NAME
xtc_lwlock_init,
xtc_lwlock_destroy,
xtc_lwlock_acquire,
xtc_lwlock_acquire_cond,
xtc_lwlock_release,
xtc_lwlock_held_by_me,
xtc_lwlock_held_by_me_in_mode,
xtc_lwlock_track_enable,
xtc_lwlock_track_violations,
xtc_lwlock_track_reset,
xtc_lwlock_track_set_handler —
lightweight lock with shared / exclusive modes
SYNOPSIS
#include <xtc.h>
#include <xtc_lwlock.h>
int
xtc_lwlock_init(xtc_lwlock_t
*lock, uint16_t
tranche);
void
xtc_lwlock_destroy(xtc_lwlock_t
*lock);
int
xtc_lwlock_acquire(xtc_lwlock_t
*lock, xtc_lwlock_mode_t
mode);
int
xtc_lwlock_acquire_cond(xtc_lwlock_t
*lock, xtc_lwlock_mode_t
mode);
void
xtc_lwlock_release(xtc_lwlock_t
*lock);
int
xtc_lwlock_held_by_me(const
xtc_lwlock_t *lock);
int
xtc_lwlock_held_by_me_in_mode(const
xtc_lwlock_t *lock,
xtc_lwlock_mode_t
mode);
void
xtc_lwlock_track_enable(int
on);
long
xtc_lwlock_track_violations(void);
void
xtc_lwlock_track_reset(void);
void
xtc_lwlock_track_set_handler(xtc_lwlock_track_fn
fn, void
*user);
DESCRIPTION
xtc_lwlock is a lightweight lock with
shared (reader) and exclusive (writer) modes. Single atomic on the fast
path; pthread_mutex / cond on the contended path. Ported from PostgreSQL's
src/backend/storage/lmgr/lwlock.c.
The optional lock-order (WITNESS)
tracker is off by default.
xtc_lwlock_track_enable()
turns it on (and off); while on, each acquire records the order
“tranche A was held when tranche B was acquired”, keyed by the
lock's tranche, and an acquisition that reverses a previously-seen order is
a lock-order inversion -- the precursor of a two-lock deadlock the lwlock
primitive cannot otherwise detect.
xtc_lwlock_track_violations()
returns the running count;
xtc_lwlock_track_set_handler()
registers a callback fired with (held_tranche, acquired_tranche) on each
inversion; and
xtc_lwlock_track_reset()
clears the edge set and counter. The tracker has overhead and is intended
for test and staging builds, not production hot paths.
The lock state is encoded in one _Atomic
uint32_t: the high three bits hold the
LW_FLAG_HAS_WAITERS,
LW_FLAG_WAKE_IN_PROGRESS, and
LW_FLAG_QUEUE_LOCKED flags; the low bits hold either
the shared-holder count or the LW_VAL_EXCLUSIVE
sentinel. An uncontended acquire is one CAS.
xtc_lwlock_init()
initialises the lock in place. tranche is a user tag
for diagnostics (groups locks by purpose so profilers can attribute
contention).
xtc_lwlock_acquire()
blocks until the calling thread holds the lock in
mode:
XTC_LW_SHARED- Multiple threads can hold the lock concurrently in shared mode. Excluded by an exclusive holder.
XTC_LW_EXCLUSIVE- Only one thread holds the lock; excludes all readers.
xtc_lwlock_acquire_cond()
is the non-blocking variant: returns XTC_OK if the
acquire succeeded immediately, XTC_E_AGAIN
otherwise.
xtc_lwlock_release()
drops the lock in whichever mode the calling thread acquired it. The mode is
tracked in a per-thread held-list so the caller does not need to pass it
back.
xtc_lwlock_held_by_me()
returns 1 if the calling thread currently holds lock
in any mode, 0 otherwise. Useful in assertions and in code that needs to
call a function that might or might not already hold a particular lock.
xtc_lwlock_held_by_me_in_mode()
narrows that test to a specific mode: it returns 1
only if the calling thread holds lock in exactly that
mode.
CHOOSING BETWEEN LOCKS
xtc ships several locks; pick by workload:
- xtc_lwlock
- General-purpose reader/writer. Best for short critical sections with mixed reader/writer ratio. This page.
- xtc_lrlock
- Wait-free reads via two-copy publish. Best for read-heavy workloads (read:write ratio > 50:1) where reads must never block. See xtc_lrlock(3).
- xtc_lockmgr
- Transactional locking with deadlock detection, multiple modes, victim selection. Best for database-style workloads with named lockable objects. See xtc_lockmgr(3).
- xtc_amutex
- Async-aware mutex; integrates with the loop scheduler. Use for critical sections that span async I/O. See xtc_sync(3).
RETURN VALUES
xtc_lwlock_init(),
xtc_lwlock_acquire(), and
xtc_lwlock_acquire_cond() return
XTC_OK on success or a negative
XTC_E_* code.
EXAMPLES
xtc_lwlock_t lk; xtc_lwlock_init(&lk, /* tranche */ 1); /* hot path: reader */ xtc_lwlock_acquire(&lk, XTC_LW_SHARED); read_state(); xtc_lwlock_release(&lk); /* mutator */ xtc_lwlock_acquire(&lk, XTC_LW_EXCLUSIVE); update_state(); xtc_lwlock_release(&lk); xtc_lwlock_destroy(&lk);
SEE ALSO
HISTORY
Ported from PostgreSQL's lrlck branch. Appeared in xtc 0.1.
| May 28, 2026 | Debian |