xtc_lockmgr(3)
---xtc_lockmgr(3)
transactional lock manager with deadlock detection
| XTC_LOCKMGR(3) | Library Functions Manual | XTC_LOCKMGR(3) |
NAME
xtc_lockmgr_create,
xtc_lockmgr_destroy,
xtc_lockmgr_id,
xtc_lockmgr_id_free,
xtc_lockmgr_id_set_timeout,
xtc_lock_get, xtc_lock_put,
xtc_lock_release_all,
xtc_lock_upgrade,
xtc_lock_downgrade,
xtc_lock_vec,
xtc_lockmgr_check_deadlocks,
xtc_lockmgr_stat,
xtc_lockmgr_n_held,
xtc_lockmgr_n_waiting,
xtc_lockmgr_failchk —
transactional lock manager with deadlock
detection
SYNOPSIS
#include <xtc.h>
#include <xtc_lockmgr.h>
int
xtc_lockmgr_create(const
xtc_lockmgr_opts_t *opts,
xtc_lockmgr_t **out);
void
xtc_lockmgr_destroy(xtc_lockmgr_t
*m);
int
xtc_lockmgr_id(xtc_lockmgr_t
*m, xtc_locker_t
*out);
int
xtc_lockmgr_id_free(xtc_lockmgr_t
*m, xtc_locker_t
locker);
int
xtc_lockmgr_id_set_timeout(xtc_lockmgr_t
*m, xtc_locker_t l,
int64_t timeout_ns);
int
xtc_lock_get(xtc_lockmgr_t
*m, xtc_locker_t
locker, const void
*key, size_t
key_size, xtc_lock_mode_t
mode, int64_t
timeout_ns);
int
xtc_lock_put(xtc_lockmgr_t
*m, xtc_locker_t
locker, const void
*key, size_t
key_size);
int
xtc_lock_release_all(xtc_lockmgr_t
*m, xtc_locker_t
locker);
int
xtc_lock_upgrade(xtc_lockmgr_t
*m, xtc_locker_t
locker, const void
*obj, size_t
obj_size, xtc_lock_mode_t
new_mode);
int
xtc_lock_downgrade(xtc_lockmgr_t
*m, xtc_locker_t
locker, const void
*obj, size_t
obj_size, xtc_lock_mode_t
new_mode);
int
xtc_lock_vec(xtc_lockmgr_t
*m, xtc_locker_t
locker, const
xtc_lock_req_t *reqs, int
n_reqs, int64_t
timeout_ns);
int
xtc_lockmgr_check_deadlocks(xtc_lockmgr_t
*m, int
*n_aborted);
int
xtc_lockmgr_stat(xtc_lockmgr_t
*m, xtc_lockmgr_stat_t
*out);
int
xtc_lockmgr_n_held(const
xtc_lockmgr_t *m);
int
xtc_lockmgr_n_waiting(const
xtc_lockmgr_t *m);
int
xtc_lockmgr_failchk(xtc_lockmgr_t
*m);
DESCRIPTION
xtc_lockmgr is a transactional lock
manager modeled on Berkeley DB's lock_*.c subsystem.
It provides:
- Named lockable objects identified by arbitrary (key, key_size) byte strings.
- Nine lock modes via the BDB ‘read-intent-write’ matrix (XTC_LOCK_NL, XTC_LOCK_S, XTC_LOCK_X, XTC_LOCK_WAIT, XTC_LOCK_IS, XTC_LOCK_IX, XTC_LOCK_IWR, XTC_LOCK_RU, XTC_LOCK_WW), or a caller-supplied conflict matrix.
- Deadlock detection in two flavours:
XTC_LOCK_DETECT_PERIODICruns a background thread; theXTC_LOCK_DETECT_ON_BLOCKmode runs synchronously every time a requestor would block. - Eight victim policies (XTC_LOCK_VICTIM_RANDOM, OLDEST, YOUNGEST,
MIN_LOCKS, MAX_LOCKS, MIN_WRITE, MAX_WRITE, EXPIRE) plus
XTC_LOCK_VICTIM_CUSTOMwhich delegates to a caller-supplied callback. - Compound atomic acquires via
xtc_lock_vec() (N requests succeed-or-rollback). - Per-locker timeouts and statistics.
xtc_lockmgr_create()
opens a lock manager with the given options. Options control partition count
(for hash sharding), detector mode and interval, victim policy, and the
conflict matrix.
xtc_lockmgr_id()
allocates a locker handle (think transaction id). Hold one per in-flight
transaction; passing it to xtc_lock_get() identifies
which transaction is asking.
xtc_lock_get()
acquires mode on the named object. Returns:
XTC_OK- The lock is held by locker.
XTC_E_AGAIN- The timeout_ns elapsed without acquiring.
XTC_E_DEADLK- The deadlock detector chose locker as a victim; the call rolls back any partial state.
XTC_E_INVAL- Bad arguments or unknown locker.
xtc_lock_put()
releases the named lock. Order of release does not matter; the lockmgr
tracks per-locker held lists.
xtc_lockmgr_id_set_timeout()
sets a per-locker deadline: once l has held its locks
past timeout_ns, the periodic detector treats it as
expired for victim selection under the EXPIRE policy. A negative value
disables expiry.
xtc_lock_release_all()
drops every lock held by locker in one call, the
normal end-of-transaction sweep.
xtc_lock_upgrade()
and
xtc_lock_downgrade()
atomically change the mode of a lock already held on
obj to new_mode. Upgrade may
block (returning XTC_E_AGAIN on a zero timeout);
downgrade never blocks and promotes any waiters the weaker mode no longer
conflicts with.
xtc_lock_vec()
performs an atomic compound acquire. Either all requested locks are granted,
or none are (if any single grant would block or be rejected); no partial
state is left.
xtc_lockmgr_check_deadlocks()
runs the cycle-detection algorithm synchronously and aborts any victims it
finds. Useful in XTC_LOCK_DETECT_NONE mode where the
caller drives detection.
xtc_lockmgr_stat()
fills out with current counts: held, waiting, total
acquires, total releases, deadlocks found, victims aborted, etc. No locks
held during the snapshot (counters are atomic).
xtc_lockmgr_failchk()
sweeps for crashed lockers (those whose owning thread has exited without
releasing) and reclaims their locks.
xtc_lockmgr_n_held()
and
xtc_lockmgr_n_waiting()
return the current number of granted and blocked lock requests respectively
-- lightweight gauges for monitoring.
CHOOSING vs. xtc_lwlock / xtc_lrlock
Use xtc_lockmgr when:
- Locks are named by user-supplied keys (e.g. table name, page id) rather than living in a fixed location.
- You need multiple lock modes beyond shared / exclusive (intent locks for hierarchical locking).
- You want deadlock detection out of the box.
- Compound acquires must be atomic.
CUSTOM VICTIM PICKER
Setting opts.victim to
XTC_LOCK_VICTIM_CUSTOM and providing
opts.victim_pick_fn delegates the choice to user
code:
typedef int (*xtc_lock_victim_pick_fn)(
const uint64_t *candidate_lockers, int n_candidates,
void *user);
The callback receives the locker IDs in the cycle and returns an index in [0, n_candidates]. See examples/04_lockmgr_demo.c for a deck-shuffled randomised picker.
SEE ALSO
HISTORY
Modeled on Berkeley DB's lock_*.c subsystem. Appeared in xtc 0.1.
| May 28, 2026 | Debian |