Locks a virMutex on creation and unlocks it in its destructor.
The VIR_LOCK_GUARD macro is used instead of "g_auto(virLockGuard)" to
work around a clang issue (see
https://bugs.llvm.org/show_bug.cgi?id=3888
and
https://bugs.llvm.org/show_bug.cgi?id=43482).
Typical usage:
void function(virMutex *m)
{
VIR_LOCK_GUARD lock = virLockGuardLock(m);
/* `m` is locked, and released automatically on scope exit */
...
while (expression) {
VIR_LOCK_GUARD lock2 = virLockGuardLock(...);
/* similar */
}
}
Signed-off-by: Tim Wiederhake <twiederh(a)redhat.com>
---
src/libvirt_private.syms | 2 ++
src/util/virthread.c | 15 +++++++++++++++
src/util/virthread.h | 10 ++++++++++
3 files changed, 27 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ba3462d849..4cfe6c17eb 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3376,6 +3376,8 @@ virCondInit;
virCondSignal;
virCondWait;
virCondWaitUntil;
+virLockGuardLock;
+virLockGuardUnlock;
virMutexDestroy;
virMutexInit;
virMutexInitRecursive;
diff --git a/src/util/virthread.c b/src/util/virthread.c
index e89c1a09fb..5422bb74fd 100644
--- a/src/util/virthread.c
+++ b/src/util/virthread.c
@@ -96,6 +96,21 @@ void virMutexUnlock(virMutex *m)
pthread_mutex_unlock(&m->lock);
}
+virLockGuard virLockGuardLock(virMutex *m)
+{
+ virLockGuard l = { m };
+ virMutexLock(m);
+ return l;
+}
+
+void virLockGuardUnlock(virLockGuard *l)
+{
+ if (!l || !l->mutex)
+ return;
+
+ virMutexUnlock(g_steal_pointer(&l->mutex));
+}
+
int virRWLockInit(virRWLock *m)
{
diff --git a/src/util/virthread.h b/src/util/virthread.h
index 55c8263ae6..6cdaf2820e 100644
--- a/src/util/virthread.h
+++ b/src/util/virthread.h
@@ -31,6 +31,11 @@ struct virMutex {
pthread_mutex_t lock;
};
+typedef struct virLockGuard virLockGuard;
+struct virLockGuard {
+ virMutex *mutex;
+};
+
typedef struct virRWLock virRWLock;
struct virRWLock {
pthread_rwlock_t lock;
@@ -121,6 +126,11 @@ void virMutexLock(virMutex *m);
void virMutexUnlock(virMutex *m);
+virLockGuard virLockGuardLock(virMutex *m);
+void virLockGuardUnlock(virLockGuard *l);
+G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(virLockGuard, virLockGuardUnlock);
+#define VIR_LOCK_GUARD g_auto(virLockGuard) G_GNUC_UNUSED
+
int virRWLockInit(virRWLock *m) G_GNUC_WARN_UNUSED_RESULT;
void virRWLockDestroy(virRWLock *m);
--
2.31.1