---
name: "ck_elide"
section: "3"
platform: "linux"
package: "libck-dev"
version: "0.7.2-6"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/ck_elide"
---

# ck\_elide(3)

lock elision wrappers

## NAME

**CK\_ELIDE\_PROTOTYPE**, **CK\_ELIDE\_LOCK\_ADAPTIVE**, **CK\_ELIDE\_UNLOCK\_ADAPTIVE**, **CK\_ELIDE\_LOCK**, **CK\_ELIDE\_UNLOCK**, **CK\_ELIDE\_TRYLOCK\_PROTOTYPE**, **CK\_ELIDE\_TRYLOCK** – lock elision wrappers

## LIBRARY

Concurrency Kit (libck, -lck)

## SYNOPSIS

**#include \<ck\_elide.h\>**

ck\_elide\_stat\_t stat = CK\_ELIDE\_STAT\_INITIALIZER;

*void*\

**ck\_elide\_stat\_init**(*ck\_elide\_stat\_t \**);

struct ck\_elide\_config config = CK\_ELIDE\_CONFIG\_DEFAULT\_INITIALIZER;

```
struct ck_elide_config {
	unsigned short skip_busy;
	short retry_busy;
	unsigned short skip_other;
	short retry_other;
	unsigned short skip_conflict;
	short retry_conflict;
};
```

**CK\_ELIDE\_PROTOTYPE**(*NAME*, *TYPE*, *LOCK\_PREDICATE*, *LOCK\_FUNCTION*, *UNLOCK\_PREDICATE*, *UNLOCK\_FUNCTION*);

**CK\_ELIDE\_LOCK\_ADAPTIVE**(*NAME*, *ck\_elide\_stat\_t \**, *struct ck\_elide\_config \**, *TYPE \**);

**CK\_ELIDE\_UNLOCK\_ADAPTIVE**(*NAME*, *ck\_elide\_stat\_t \**, *TYPE \**);

**CK\_ELIDE\_LOCK**(*NAME*, *TYPE \**);

**CK\_ELIDE\_UNLOCK**(*NAME*, *TYPE \**);

**CK\_ELIDE\_TRYLOCK\_PROTOTYPE**(*NAME*, *TYPE*, *LOCK\_PREDICATE*, *TRYLOCK\_FUNCTION*);

## DESCRIPTION

These macros implement lock elision wrappers for a user-specified single-argument lock interface. The wrappers will attempt to elide lock acquisition, allowing concurrent execution of critical sections that do not issue conflicting memory operations. If any threads have successfully elided a lock acquisition, conflicting memory operations will roll-back any side-effects of the critical section and force every thread to retry the lock acquisition regularly.

**CK\_ELIDE\_LOCK**(), **CK\_ELIDE\_UNLOCK**(), **CK\_ELIDE\_LOCK\_ADAPTIVE**(), and **CK\_ELIDE\_UNLOCK\_ADAPTIVE**() macros require a previous **CK\_ELIDE\_PROTOTYPE**() with the same *NAME*. Elision is attempted if the *LOCK\_PREDICATE* function returns false. If *LOCK\_PREDICATE* returns true then elision is aborted and *LOCK\_FUNCTION* is executed instead. If any threads are in an elided critical section, *LOCK\_FUNCTION* must force them to rollback through a conflicting memory operation. The *UNLOCK\_PREDICATE* function must return true if the lock is acquired by the caller, meaning that the lock was not successfully elided. If *UNLOCK\_PREDICATE* returns true, then the *UNLOCK\_FUNCTION* is executed. If RTM is unsupported (no CK\_F\_PR\_RTM macro) then **CK\_ELIDE\_LOCK**() and **CK\_ELIDE\_LOCK\_ADAPTIVE**() will immediately call **LOCK\_FUNCTION**(). **CK\_ELIDE\_UNLOCK**() and **CK\_ELIDE\_UNLOCK\_ADAPTIVE**() will immediately call **UNLOCK\_FUNCTION**().

**CK\_ELIDE\_TRYLOCK**() requires a previous **CK\_ELIDE\_TRYLOCK\_PROTOTYPE**() with the same name. Elision is attempted if the *LOCK\_PREDICATE* function returns false. If *LOCK\_PREDICATE* returns true or if elision fails then the operation is aborted. If RTM is unsupported (no CK\_F\_PR\_RTM macro) then **CK\_ELIDE\_TRYLOCK**() will immediately call **TRYLOCK\_FUNCTION**().

**CK\_ELIDE\_LOCK\_ADAPTIVE**() and **CK\_ELIDE\_UNLOCK\_ADAPTIVE**() will adapt the elision behavior associated with lock operations according to the run-time behavior of the program. This behavior is defined by the ck\_elide\_config structure pointer passed to **CK\_ELIDE\_LOCK\_ADAPTIVE**(). A thread-local ck\_elide\_stat structure must be passed to both **CK\_ELIDE\_LOCK\_ADAPTIVE**() and **CK\_ELIDE\_UNLOCK\_ADAPTIVE**(). This structure is expected to be unique for different workloads, may not be re-used in recursive acquisitions and must match the lifetime of the lock it is associated with. It is safe to mix adaptive calls with best-effort calls.

Both ck\_spinlock.h and ck\_rwlock.h define ck\_elide wrappers under the ck\_spinlock and ck\_rwlock namespace, respectively.

## EXAMPLES

This example utilizes built-in lock elision facilities in ck\_rwlock and ck\_spinlock.

```
#include <ck_rwlock.h>
#include <ck_spinlock.h>
static ck_rwlock_t rw = CK_RWLOCK_INITIALIZER;
static struct ck_elide_config rw_config =
    CK_ELIDE_CONFIG_DEFAULT_INITIALIZER;
static __thread ck_elide_stat_t rw_stat =
    CK_ELIDE_STAT_INITIALIZER;
static ck_spinlock_t spinlock = CK_SPINLOCK_INITIALIZER;
static struct ck_elide_config spinlock_config =
    CK_ELIDE_CONFIG_DEFAULT_INITIALIZER;
static __thread ck_elide_stat_t spinlock_stat =
    CK_ELIDE_STAT_INITIALIZER;
void
function(void)
{
	/* Lock-unlock write-side lock in weak best-effort manner. */
	CK_ELIDE_LOCK(ck_rwlock_write, &rw);
	CK_ELIDE_UNLOCK(ck_rwlock_write, &rw);
	/* Attempt to acquire the write-side lock. */
	if (CK_ELIDE_TRYLOCK(ck_rwlock_write, &rw) == true)
		CK_ELIDE_UNLOCK(ck_rwlock_write, &rw);
	/* Lock-unlock read-side lock in weak best-effort manner. */
	CK_ELIDE_LOCK(ck_rwlock_read, &rw);
	CK_ELIDE_UNLOCK(ck_rwlock_read, &rw);
	/* Attempt to acquire the read-side lock. */
	if (CK_ELIDE_TRYLOCK(ck_rwlock_read, &rw) == true)
		CK_ELIDE_UNLOCK(ck_rwlock_read, &rw);
	/* Lock-unlock write-side lock in an adaptive manner. */
	CK_ELIDE_LOCK_ADAPTIVE(ck_rwlock_write, &rw_stat,
	    &rw_config, &rw);
	CK_ELIDE_UNLOCK_ADAPTIVE(ck_rwlock_write, &rw_stat,
	    &rw_config, &rw);
	/* Lock-unlock read-side lock in an adaptive manner. */
	CK_ELIDE_LOCK_ADAPTIVE(ck_rwlock_read, &rw_stat,
	    &rw_config, &rw);
	CK_ELIDE_UNLOCK_ADAPTIVE(ck_rwlock_read, &rw_stat,
	    &rw_config, &rw);
	/* Lock-unlock spinlock in weak best-effort manner. */
	CK_ELIDE_LOCK(ck_spinlock, &spinlock);
	CK_ELIDE_UNLOCK(ck_spinlock, &spinlock);
	/* Attempt to acquire the lock. */
	if (CK_ELIDE_TRYLOCK(ck_spinlock, &lock) == true)
		CK_ELIDE_UNLOCK(ck_spinlock, &spinlock);
	/* Lock-unlock spinlock in an adaptive manner. */
	CK_ELIDE_LOCK_ADAPTIVE(ck_spinlock, &spinlock_stat,
	    &spinlock_config, &spinlock);
	CK_ELIDE_UNLOCK_ADAPTIVE(ck_spinlock, &spinlock_stat,
	    &spinlock_config, &spinlock);
}
```

In this example, user-defined locking functions are provided an elision implementation.

```
/* Assume lock_t has been previously defined. */
#include <ck_elide.h>
/*
 * This function returns true if the lock is unavailable at the time
 * it was called or false if the lock is available.
 */
bool is_locked(lock_t *);
/*
 * This function acquires the supplied lock.
 */
void lock(lock_t *);
/*
 * This function releases the lock.
 */
void unlock(lock_t *);
CK_ELIDE_PROTOTYPE(my_lock, lock_t, is_locked, lock, is_locked, unlock)
static lock_t lock;
void
function(void)
{
	CK_ELIDE_LOCK(my_lock, &lock);
	CK_ELIDE_UNLOCK(my_lock, &lock);
}
```

## SEE ALSO

[ck\_rwlock(3)](/ck_rwlock/3.md), [ck\_spinlock(3)](/ck_spinlock/3.md)

Ravi Rajwar and James R. Goodman. 2001. Speculative lock elision: enabling highly concurrent multithreaded execution. In Proceedings of the 34th annual ACM/IEEE international symposium on Microarchitecture (MICRO 34). IEEE Computer Society, Washington, DC, USA, 294-305.

Additional information available at http://en.wikipedia.org/wiki/Transactional\_Synchronization\_Extensions and http://concurrencykit.org/
