.\" Automatically generated by Pandoc 2.9.2.1
.\"
.TH "" "" "2023-05-31" "PMDK - " "PMDK Programmer's Manual"
.hy
.\" SPDX-License-Identifier: BSD-3-Clause
.\" Copyright 2017-2018, Intel Corporation
.SH NAME
.PP
\f[B]pmemobj_mutex_zero\f[R](), \f[B]pmemobj_mutex_lock\f[R](),
\f[B]pmemobj_mutex_timedlock\f[R](), \f[B]pmemobj_mutex_trylock\f[R](),
\f[B]pmemobj_mutex_unlock\f[R](),
.PP
\f[B]pmemobj_rwlock_zero\f[R](), \f[B]pmemobj_rwlock_rdlock\f[R](),
\f[B]pmemobj_rwlock_wrlock\f[R](),
\f[B]pmemobj_rwlock_timedrdlock\f[R](),
\f[B]pmemobj_rwlock_timedwrlock\f[R](),
\f[B]pmemobj_rwlock_tryrdlock\f[R](),
\f[B]pmemobj_rwlock_trywrlock\f[R](), \f[B]pmemobj_rwlock_unlock\f[R](),
.PP
\f[B]pmemobj_cond_zero\f[R](), \f[B]pmemobj_cond_broadcast\f[R](),
\f[B]pmemobj_cond_signal\f[R](), \f[B]pmemobj_cond_timedwait\f[R](),
\f[B]pmemobj_cond_wait\f[R]() - pmemobj synchronization primitives
.SH SYNOPSIS
.IP
.nf
\f[C]
#include <libpmemobj.h>

void pmemobj_mutex_zero(PMEMobjpool *pop, PMEMmutex *mutexp);
int pmemobj_mutex_lock(PMEMobjpool *pop, PMEMmutex *mutexp);
int pmemobj_mutex_timedlock(PMEMobjpool *pop, PMEMmutex *restrict mutexp,
    const struct timespec *restrict abs_timeout);
int pmemobj_mutex_trylock(PMEMobjpool *pop, PMEMmutex *mutexp);
int pmemobj_mutex_unlock(PMEMobjpool *pop, PMEMmutex *mutexp);

void pmemobj_rwlock_zero(PMEMobjpool *pop, PMEMrwlock *rwlockp);
int pmemobj_rwlock_rdlock(PMEMobjpool *pop, PMEMrwlock *rwlockp);
int pmemobj_rwlock_wrlock(PMEMobjpool *pop, PMEMrwlock *rwlockp);
int pmemobj_rwlock_timedrdlock(PMEMobjpool *pop, PMEMrwlock *restrict rwlockp,
    const struct timespec *restrict abs_timeout);
int pmemobj_rwlock_timedwrlock(PMEMobjpool *pop, PMEMrwlock *restrict rwlockp,
    const struct timespec *restrict abs_timeout);
int pmemobj_rwlock_tryrdlock(PMEMobjpool *pop, PMEMrwlock *rwlockp);
int pmemobj_rwlock_trywrlock(PMEMobjpool *pop, PMEMrwlock *rwlockp);
int pmemobj_rwlock_unlock(PMEMobjpool *pop, PMEMrwlock *rwlockp);

void pmemobj_cond_zero(PMEMobjpool *pop, PMEMcond *condp);
int pmemobj_cond_broadcast(PMEMobjpool *pop, PMEMcond *condp);
int pmemobj_cond_signal(PMEMobjpool *pop, PMEMcond *condp);
int pmemobj_cond_timedwait(PMEMobjpool *pop, PMEMcond *restrict condp,
    PMEMmutex *restrict mutexp, const struct timespec *restrict abs_timeout);
int pmemobj_cond_wait(PMEMobjpool *pop, PMEMcond *restrict condp,
    PMEMmutex *restrict mutexp);
\f[R]
.fi
.SH DESCRIPTION
.PP
\f[B]libpmemobj\f[R](7) provides several types of synchronization
primitives designed to be used with persistent memory.
The pmem-aware lock implementation is based on the standard POSIX
Threads Library, as described in \f[B]pthread_mutex_init\f[R](3),
\f[B]pthread_rwlock_init\f[R](3) and \f[B]pthread_cond_init\f[R](3).
Pmem-aware locks provide semantics similar to standard \f[B]pthread\f[R]
locks, except that they are embedded in pmem-resident objects and are
considered initialized by zeroing them.
Therefore, locks allocated with \f[B]pmemobj_zalloc\f[R](3) or
\f[B]pmemobj_tx_zalloc\f[R](3) do not require another initialization
step.
For performance reasons, they are also padded up to 64 bytes (cache line
size).
.PP
On FreeBSD, since all \f[B]pthread\f[R] locks are dynamically allocated,
while the lock object is still padded up to 64 bytes for consistency
with Linux, only the pointer to the lock is embedded in the
pmem-resident object.
\f[B]libpmemobj\f[R](7) transparently manages freeing of the locks when
the pool is closed.
.PP
The fundamental property of pmem-aware locks is their automatic
reinitialization every time the persistent object store pool is opened.
Thus, all the pmem-aware locks may be considered initialized (unlocked)
immediately after the pool is opened, regardless of their state at the
time the pool was closed for the last time.
.PP
Pmem-aware mutexes, read/write locks and condition variables must be
declared with the \f[I]PMEMmutex\f[R], \f[I]PMEMrwlock\f[R], or
\f[I]PMEMcond\f[R] type, respectively.
.PP
The \f[B]pmemobj_mutex_zero\f[R]() function explicitly initializes the
pmem-aware mutex \f[I]mutexp\f[R] by zeroing it.
Initialization is not necessary if the object containing the mutex has
been allocated using \f[B]pmemobj_zalloc\f[R](3) or
\f[B]pmemobj_tx_zalloc\f[R](3).
.PP
The \f[B]pmemobj_mutex_lock\f[R]() function locks the pmem-aware mutex
\f[I]mutexp\f[R].
If the mutex is already locked, the calling thread will block until the
mutex becomes available.
If this is the first use of the mutex since the opening of the pool
\f[I]pop\f[R], the mutex is automatically reinitialized and then locked.
.PP
\f[B]pmemobj_mutex_timedlock\f[R]() performs the same action as
\f[B]pmemobj_mutex_lock\f[R](), but will not wait beyond
\f[I]abs_timeout\f[R] to obtain the lock before returning.
.PP
The \f[B]pmemobj_mutex_trylock\f[R]() function locks pmem-aware mutex
\f[I]mutexp\f[R].
If the mutex is already locked, \f[B]pthread_mutex_trylock\f[R]() will
not block waiting for the mutex, but will return an error.
If this is the first use of the mutex since the opening of the pool
\f[I]pop\f[R], the mutex is automatically reinitialized and then locked.
.PP
The \f[B]pmemobj_mutex_unlock\f[R]() function unlocks the pmem-aware
mutex \f[I]mutexp\f[R].
Undefined behavior follows if a thread tries to unlock a mutex that has
not been locked by it, or if a thread tries to release a mutex that is
already unlocked or has not been initialized.
.PP
The \f[B]pmemobj_rwlock_zero\f[R]() function is used to explicitly
initialize the pmem-aware read/write lock \f[I]rwlockp\f[R] by zeroing
it.
Initialization is not necessary if the object containing the lock has
been allocated using \f[B]pmemobj_zalloc\f[R](3) or
\f[B]pmemobj_tx_zalloc\f[R](3).
.PP
The \f[B]pmemobj_rwlock_rdlock\f[R]() function acquires a read lock on
\f[I]rwlockp\f[R], provided that the lock is not presently held for
writing and no writer threads are presently blocked on the lock.
If the read lock cannot be acquired immediately, the calling thread
blocks until it can acquire the lock.
If this is the first use of the lock since the opening of the pool
\f[I]pop\f[R], the lock is automatically reinitialized and then
acquired.
.PP
\f[B]pmemobj_rwlock_timedrdlock\f[R]() performs the same action as
\f[B]pmemobj_rwlock_rdlock\f[R](), but will not wait beyond
\f[I]abs_timeout\f[R] to obtain the lock before returning.
A thread may hold multiple concurrent read locks.
If so, \f[B]pmemobj_rwlock_unlock\f[R]() must be called once for each
lock obtained.
The results of acquiring a read lock while the calling thread holds a
write lock are undefined.
.PP
The \f[B]pmemobj_rwlock_wrlock\f[R]() function blocks until a write lock
can be acquired against read/write lock \f[I]rwlockp\f[R].
If this is the first use of the lock since the opening of the pool
\f[I]pop\f[R], the lock is automatically reinitialized and then
acquired.
.PP
\f[B]pmemobj_rwlock_timedwrlock\f[R]() performs the same action, but
will not wait beyond \f[I]abs_timeout\f[R] to obtain the lock before
returning.
.PP
The \f[B]pmemobj_rwlock_tryrdlock\f[R]() function performs the same
action as \f[B]pmemobj_rwlock_rdlock\f[R](), but does not block if the
lock cannot be immediately obtained.
The results are undefined if the calling thread already holds the lock
at the time the call is made.
.PP
The \f[B]pmemobj_rwlock_trywrlock\f[R]() function performs the same
action as \f[B]pmemobj_rwlock_wrlock\f[R](), but does not block if the
lock cannot be immediately obtained.
The results are undefined if the calling thread already holds the lock
at the time the call is made.
.PP
The \f[B]pmemobj_rwlock_unlock\f[R]() function is used to release the
read/write lock previously obtained by
\f[B]pmemobj_rwlock_rdlock\f[R](), \f[B]pmemobj_rwlock_wrlock\f[R](),
\f[B]pthread_rwlock_tryrdlock\f[R](), or
\f[B]pmemobj_rwlock_trywrlock\f[R]().
.PP
The \f[B]pmemobj_cond_zero\f[R]() function explicitly initializes the
pmem-aware condition variable \f[I]condp\f[R] by zeroing it.
Initialization is not necessary if the object containing the condition
variable has been allocated using \f[B]pmemobj_zalloc\f[R](3) or
\f[B]pmemobj_tx_zalloc\f[R](3).
.PP
The difference between \f[B]pmemobj_cond_broadcast\f[R]() and
\f[B]pmemobj_cond_signal\f[R]() is that the former unblocks all threads
waiting for the condition variable, whereas the latter blocks only one
waiting thread.
If no threads are waiting on \f[I]condp\f[R], neither function has any
effect.
If more than one thread is blocked on a condition variable, the used
scheduling policy determines the order in which threads are unblocked.
The same mutex used for waiting must be held while calling either
function.
Although neither function strictly enforces this requirement, undefined
behavior may follow if the mutex is not held.
.PP
The \f[B]pmemobj_cond_timedwait\f[R]() and \f[B]pmemobj_cond_wait\f[R]()
functions block on a condition variable.
They must be called with mutex \f[I]mutexp\f[R] locked by the calling
thread, or undefined behavior results.
These functions atomically release mutex \f[I]mutexp\f[R] and cause the
calling thread to block on the condition variable \f[I]condp\f[R];
atomically here means \[lq]atomically with respect to access by another
thread to the mutex and then the condition variable\[rq].
That is, if another thread is able to acquire the mutex after the
about-to-block thread has released it, then a subsequent call to
\f[B]pmemobj_cond_broadcast\f[R]() or \f[B]pmemobj_cond_signal\f[R]() in
that thread will behave as if it were issued after the about-to-block
thread has blocked.
Upon successful return, the mutex will be locked and owned by the
calling thread.
.SH RETURN VALUE
.PP
The \f[B]pmemobj_mutex_zero\f[R](), \f[B]pmemobj_rwlock_zero\f[R]() and
\f[B]pmemobj_cond_zero\f[R]() functions return no value.
.PP
Other locking functions return 0 on success.
Otherwise, an error number will be returned to indicate the error.
.SH SEE ALSO
.PP
\f[B]pmemobj_tx_zalloc\f[R](3), \f[B]pmemobj_zalloc\f[R](3),
\f[B]pthread_cond_init\f[R](3), \f[B]pthread_mutex_init\f[R](3),
\f[B]pthread_rwlock_init\f[R](3), \f[B]libpmem\f[R](7),
\f[B]libpmemobj\f[R](7) and \f[B]<https://pmem.io>\f[R]