aboutsummaryrefslogtreecommitdiff
path: root/tests/test-rfifolock.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test-rfifolock.c')
-rw-r--r--tests/test-rfifolock.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/tests/test-rfifolock.c b/tests/test-rfifolock.c
new file mode 100644
index 0000000000..0572ebb42a
--- /dev/null
+++ b/tests/test-rfifolock.c
@@ -0,0 +1,91 @@
+/*
+ * RFifoLock tests
+ *
+ * Copyright Red Hat, Inc. 2013
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include <glib.h>
+#include "qemu-common.h"
+#include "qemu/rfifolock.h"
+
+static void test_nesting(void)
+{
+ RFifoLock lock;
+
+ /* Trivial test, ensure the lock is recursive */
+ rfifolock_init(&lock, NULL, NULL);
+ rfifolock_lock(&lock);
+ rfifolock_lock(&lock);
+ rfifolock_lock(&lock);
+ rfifolock_unlock(&lock);
+ rfifolock_unlock(&lock);
+ rfifolock_unlock(&lock);
+ rfifolock_destroy(&lock);
+}
+
+typedef struct {
+ RFifoLock lock;
+ int fd[2];
+} CallbackTestData;
+
+static void rfifolock_cb(void *opaque)
+{
+ CallbackTestData *data = opaque;
+ int ret;
+ char c = 0;
+
+ ret = write(data->fd[1], &c, sizeof(c));
+ g_assert(ret == 1);
+}
+
+static void *callback_thread(void *opaque)
+{
+ CallbackTestData *data = opaque;
+
+ /* The other thread holds the lock so the contention callback will be
+ * invoked...
+ */
+ rfifolock_lock(&data->lock);
+ rfifolock_unlock(&data->lock);
+ return NULL;
+}
+
+static void test_callback(void)
+{
+ CallbackTestData data;
+ QemuThread thread;
+ int ret;
+ char c;
+
+ rfifolock_init(&data.lock, rfifolock_cb, &data);
+ ret = qemu_pipe(data.fd);
+ g_assert(ret == 0);
+
+ /* Hold lock but allow the callback to kick us by writing to the pipe */
+ rfifolock_lock(&data.lock);
+ qemu_thread_create(&thread, "callback_thread",
+ callback_thread, &data, QEMU_THREAD_JOINABLE);
+ ret = read(data.fd[0], &c, sizeof(c));
+ g_assert(ret == 1);
+ rfifolock_unlock(&data.lock);
+ /* If we got here then the callback was invoked, as expected */
+
+ qemu_thread_join(&thread);
+ close(data.fd[0]);
+ close(data.fd[1]);
+ rfifolock_destroy(&data.lock);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/nesting", test_nesting);
+ g_test_add_func("/callback", test_callback);
+ return g_test_run();
+}