PMEMOBJ_MUTEX_ZERO(3)
π PMEMOBJ_COND_BROADCAST(3) π
okay bestie, welcome to the PMDK Programmer's Manual β¨ this one is all about pmemobj synchronization primitives, and honestly? it's giving "locks but make them persistent" π
πΈ NAME πΈ
pmemobj_mutex_zero(), pmemobj_mutex_lock(), pmemobj_mutex_timedlock(), pmemobj_mutex_trylock(), pmemobj_mutex_unlock(),
pmemobj_rwlock_zero(), pmemobj_rwlock_rdlock(), pmemobj_rwlock_wrlock(), pmemobj_rwlock_timedrdlock(), pmemobj_rwlock_timedwrlock(), pmemobj_rwlock_tryrdlock(), pmemobj_rwlock_trywrlock(), pmemobj_rwlock_unlock(),
pmemobj_cond_zero(), pmemobj_cond_broadcast(), pmemobj_cond_signal(), pmemobj_cond_timedwait(), pmemobj_cond_wait() β pmemobj synchronization primitives π
β¨ SYNOPSIS β¨
#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);
π DESCRIPTION π
libpmemobj(7) hands you a whole lil squad of synchronization primitives, all built to hang out with persistent memory. The pmem-aware lock implementation is based on the standard POSIX Threads Library, exactly like pthread_mutex_init(3), pthread_rwlock_init(3) and pthread_cond_init(3) describe. π§
So here's the tea: pmem-aware locks give you semantics similar to standard pthread locks, except that they're embedded inside pmem-resident objects and they count as initialized just by zeroing them. That means locks you got from pmemobj_zalloc(3) or pmemobj_tx_zalloc(3) need literally no extra init step β slay. π And for performance reasons, they're also padded up to 64 bytes (cache line size). π
The fundamental property of pmem-aware locks is their automatic reinitialization every single time the persistent object store pool is opened. So like, all the pmem-aware locks may be considered initialized (unlocked) immediately after the pool is opened, no matter what state they were in when the pool was last closed. iconic behavior fr fr β¨
Pmem-aware mutexes, read/write locks and condition variables must be declared with the PMEMmutex, PMEMrwlock, or PMEMcond type, respectively.
π the mutex girlies π
pmemobj_mutex_zero()β explicitly initializes the pmem-aware mutexmutexpby zeroing it. You don't need to do this if the object containing the mutex was allocated usingpmemobj_zalloc(3)orpmemobj_tx_zalloc(3). π€pmemobj_mutex_lock()β locks the pmem-aware mutexmutexp. If the mutex is already locked, the calling thread will block until the mutex becomes available. And if this is the first use of the mutex since the opening of the poolpop, the mutex is automatically reinitialized and then locked. no cap π«Άpmemobj_mutex_timedlock()β does the same thing aspmemobj_mutex_lock(), but will not wait beyondabs_timeoutto obtain the lock before returning. clock's ticking bestie β°pmemobj_mutex_trylock()β locks pmem-aware mutexmutexp. If the mutex is already locked,pthread_mutex_trylock()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 poolpop, the mutex is automatically reinitialized and then locked. lowkey impatient energy, love that πpmemobj_mutex_unlock()β unlocks the pmem-aware mutexmutexp.
β οΈ undefined behavior alert: 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, that's UB territory. don't do it π
π¦ the read/write lock girlies π¦
pmemobj_rwlock_zero()β explicitly initializes the pmem-aware read/write lockrwlockpby zeroing it. Again, no initialization needed if the object containing the lock was allocated usingpmemobj_zalloc(3)orpmemobj_tx_zalloc(3). β¨pmemobj_rwlock_rdlock()β acquires a read lock onrwlockp, provided the lock isn't presently held for writing and no writer threads are presently blocked on the lock. If the read lock can't 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 poolpop, the lock is automatically reinitialized and then acquired. πΈpmemobj_rwlock_timedrdlock()β same action aspmemobj_rwlock_rdlock(), but will not wait beyondabs_timeoutto obtain the lock before returning. A thread may hold multiple concurrent read locks. If so,pmemobj_rwlock_unlock()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. πpmemobj_rwlock_wrlock()β blocks until a write lock can be acquired against read/write lockrwlockp. If this is the first use of the lock since the opening of the poolpop, the lock is automatically reinitialized and then acquired. π₯pmemobj_rwlock_timedwrlock()β same action, but will not wait beyondabs_timeoutto obtain the lock before returning. β³pmemobj_rwlock_tryrdlock()β same action aspmemobj_rwlock_rdlock(), 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. πpmemobj_rwlock_trywrlock()β same action aspmemobj_rwlock_wrlock(), 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. πpmemobj_rwlock_unlock()β releases the read/write lock previously obtained bypmemobj_rwlock_rdlock(),pmemobj_rwlock_wrlock(),pthread_rwlock_tryrdlock(), orpmemobj_rwlock_trywrlock(). bye bye lock π
π the condition variable girlies (yes this is the main character of this page) π
pmemobj_cond_zero()β explicitly initializes the pmem-aware condition variablecondpby zeroing it. Initialization is not necessary if the object containing the condition variable was allocated usingpmemobj_zalloc(3)orpmemobj_tx_zalloc(3). π§pmemobj_cond_broadcast()vspmemobj_cond_signal()β the difference between them is that the former unblocks all threads waiting for the condition variable, whereas the latter only unblocks one waiting thread. If no threads are waiting oncondp, 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.
β οΈ neither function strictly enforces that "hold the mutex" requirement, but undefined behavior may follow if the mutex is not held. so like... hold it bestie π
pmemobj_cond_timedwait()andpmemobj_cond_wait()β these block on a condition variable. They must be called with mutexmutexplocked by the calling thread, or undefined behavior results. π These functions atomically release mutexmutexpand cause the calling thread to block on the condition variablecondp; "atomically" here means "atomically with respect to access by another thread to the mutex and then the condition variable". That is, if another thread is able to acquire the mutex after the about-to-block thread has released it, then a subsequent call topmemobj_cond_broadcast()orpmemobj_cond_signal()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. π
π RETURN VALUE π
pmemobj_mutex_zero(), pmemobj_rwlock_zero() and pmemobj_cond_zero() return no value. nothing. silence. π€
All the other locking functions return 0 on success. Otherwise, an error number will be returned to indicate the error. β
π SEE ALSO π
pmemobj_tx_zalloc(3), pmemobj_zalloc(3), pthread_cond_init(3), pthread_mutex_init(3), pthread_rwlock_init(3), libpmem(7), libpmemobj(7) and https://pmem.io π«Ά
and that's the whole page bestie, you ate it fr fr π this one's from the PMDK crew, dated 2025-07-24 β go forth and lock responsibly, mwah π
β¨πΈ
π¦ where this page comes from
- fedora 43: libpmemobj-devel 2.1.0-4.fc43 Β· BSD-3-Clause
- π the page's license: BSD-3-Clause
- Copyright 2017-2018, Intel Corporation
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms