Add qemu 2.4.0
[kvmfornfv.git] / qemu / tests / test-rfifolock.c
1 /*
2  * RFifoLock tests
3  *
4  * Copyright Red Hat, Inc. 2013
5  *
6  * Authors:
7  *  Stefan Hajnoczi    <stefanha@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU LGPL, version 2 or later.
10  * See the COPYING.LIB file in the top-level directory.
11  */
12
13 #include <glib.h>
14 #include "qemu-common.h"
15 #include "qemu/rfifolock.h"
16
17 static void test_nesting(void)
18 {
19     RFifoLock lock;
20
21     /* Trivial test, ensure the lock is recursive */
22     rfifolock_init(&lock, NULL, NULL);
23     rfifolock_lock(&lock);
24     rfifolock_lock(&lock);
25     rfifolock_lock(&lock);
26     rfifolock_unlock(&lock);
27     rfifolock_unlock(&lock);
28     rfifolock_unlock(&lock);
29     rfifolock_destroy(&lock);
30 }
31
32 typedef struct {
33     RFifoLock lock;
34     int fd[2];
35 } CallbackTestData;
36
37 static void rfifolock_cb(void *opaque)
38 {
39     CallbackTestData *data = opaque;
40     int ret;
41     char c = 0;
42
43     ret = write(data->fd[1], &c, sizeof(c));
44     g_assert(ret == 1);
45 }
46
47 static void *callback_thread(void *opaque)
48 {
49     CallbackTestData *data = opaque;
50
51     /* The other thread holds the lock so the contention callback will be
52      * invoked...
53      */
54     rfifolock_lock(&data->lock);
55     rfifolock_unlock(&data->lock);
56     return NULL;
57 }
58
59 static void test_callback(void)
60 {
61     CallbackTestData data;
62     QemuThread thread;
63     int ret;
64     char c;
65
66     rfifolock_init(&data.lock, rfifolock_cb, &data);
67     ret = qemu_pipe(data.fd);
68     g_assert(ret == 0);
69
70     /* Hold lock but allow the callback to kick us by writing to the pipe */
71     rfifolock_lock(&data.lock);
72     qemu_thread_create(&thread, "callback_thread",
73                        callback_thread, &data, QEMU_THREAD_JOINABLE);
74     ret = read(data.fd[0], &c, sizeof(c));
75     g_assert(ret == 1);
76     rfifolock_unlock(&data.lock);
77     /* If we got here then the callback was invoked, as expected */
78
79     qemu_thread_join(&thread);
80     close(data.fd[0]);
81     close(data.fd[1]);
82     rfifolock_destroy(&data.lock);
83 }
84
85 int main(int argc, char **argv)
86 {
87     g_test_init(&argc, &argv, NULL);
88     g_test_add_func("/nesting", test_nesting);
89     g_test_add_func("/callback", test_callback);
90     return g_test_run();
91 }