aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2014-03-03 11:30:03 +0100
committerStefan Hajnoczi <stefanha@redhat.com>2014-03-13 14:42:21 +0100
commit2da61b671eb89fcaa306738f44eed472977d6587 (patch)
tree61673e48ab889a6ea113ff4d2be2d48d7108d1a1 /include
parent11f590b1a242492a0108da42f40f0e2b20f0a778 (diff)
rfifolock: add recursive FIFO lock
QemuMutex does not guarantee fairness and cannot be acquired recursively: Fairness means each locker gets a turn and the scheduler cannot cause starvation. Recursive locking is useful for composition, it allows a sequence of locking operations to be invoked atomically by acquiring the lock around them. This patch adds RFifoLock, a recursive lock that guarantees FIFO order. Its first user is added in the next patch. RFifoLock has one additional feature: it can be initialized with an optional contention callback. The callback is invoked whenever a thread must wait for the lock. For example, it can be used to poke the current owner so that they release the lock soon. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/qemu/rfifolock.h54
1 files changed, 54 insertions, 0 deletions
diff --git a/include/qemu/rfifolock.h b/include/qemu/rfifolock.h
new file mode 100644
index 0000000000..b23ab538a6
--- /dev/null
+++ b/include/qemu/rfifolock.h
@@ -0,0 +1,54 @@
+/*
+ * Recursive FIFO lock
+ *
+ * Copyright Red Hat, Inc. 2013
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_RFIFOLOCK_H
+#define QEMU_RFIFOLOCK_H
+
+#include "qemu/thread.h"
+
+/* Recursive FIFO lock
+ *
+ * This lock provides more features than a plain mutex:
+ *
+ * 1. Fairness - enforces FIFO order.
+ * 2. Nesting - can be taken recursively.
+ * 3. Contention callback - optional, called when thread must wait.
+ *
+ * The recursive FIFO lock is heavyweight so prefer other synchronization
+ * primitives if you do not need its features.
+ */
+typedef struct {
+ QemuMutex lock; /* protects all fields */
+
+ /* FIFO order */
+ unsigned int head; /* active ticket number */
+ unsigned int tail; /* waiting ticket number */
+ QemuCond cond; /* used to wait for our ticket number */
+
+ /* Nesting */
+ QemuThread owner_thread; /* thread that currently has ownership */
+ unsigned int nesting; /* amount of nesting levels */
+
+ /* Contention callback */
+ void (*cb)(void *); /* called when thread must wait, with ->lock
+ * held so it may not recursively lock/unlock
+ */
+ void *cb_opaque;
+} RFifoLock;
+
+void rfifolock_init(RFifoLock *r, void (*cb)(void *), void *opaque);
+void rfifolock_destroy(RFifoLock *r);
+void rfifolock_lock(RFifoLock *r);
+void rfifolock_unlock(RFifoLock *r);
+
+#endif /* QEMU_RFIFOLOCK_H */