xtc_lockmgr(3)

---

xtc_lockmgr(3)

transactional lock manager with deadlock detection

XTC_LOCKMGR(3) Library Functions Manual XTC_LOCKMGR(3)

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_failchktransactional lock manager with deadlock detection

#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);

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_PERIODIC runs a background thread; the XTC_LOCK_DETECT_ON_BLOCK mode 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_CUSTOM which delegates to a caller-supplied callback.
  • Compound atomic acquires via () (N requests succeed-or-rollback).
  • Per-locker timeouts and statistics.

() 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.

() allocates a locker handle (think transaction id). Hold one per in-flight transaction; passing it to xtc_lock_get() identifies which transaction is asking.

() acquires mode on the named object. Returns:

The lock is held by locker.
The timeout_ns elapsed without acquiring.
The deadlock detector chose locker as a victim; the call rolls back any partial state.
Bad arguments or unknown locker.

() releases the named lock. Order of release does not matter; the lockmgr tracks per-locker held lists.

() 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.

() drops every lock held by locker in one call, the normal end-of-transaction sweep.

() and () 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.

() 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.

() runs the cycle-detection algorithm synchronously and aborts any victims it finds. Useful in XTC_LOCK_DETECT_NONE mode where the caller drives detection.

() 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).

() sweeps for crashed lockers (those whose owning thread has exited without releasing) and reclaims their locks.

() and () return the current number of granted and blocked lock requests respectively -- lightweight gauges for monitoring.

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.
For everything else, prefer xtc_lwlock(3) or xtc_lrlock(3).

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.

xtc_lwlock(3), xtc_lrlock(3), xtc(7)

Modeled on Berkeley DB's lock_*.c subsystem. Appeared in xtc 0.1.

May 28, 2026 Debian

View the mdoc source