summaryrefslogtreecommitdiff
path: root/libcacard/event.c
blob: bb2f9219f9b43b3ae4017dd2bcc8a7b7067e176d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
 * event queue implementation.
 *
 * This code is licensed under the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 */

#include "qemu-common.h"
#include "qemu-thread.h"

#include "vcard.h"
#include "vreader.h"
#include "vevent.h"

VEvent *
vevent_new(VEventType type, VReader *reader, VCard *card)
{
    VEvent *new_vevent;

    new_vevent = (VEvent *)qemu_malloc(sizeof(VEvent));
    new_vevent->next = NULL;
    new_vevent->type = type;
    new_vevent->reader = vreader_reference(reader);
    new_vevent->card = vcard_reference(card);

    return new_vevent;
}

void
vevent_delete(VEvent *vevent)
{
    if (vevent == NULL) {
        return;
    }
    vreader_free(vevent->reader);
    vcard_free(vevent->card);
    qemu_free(vevent);
}

/*
 * VEvent queue management
 */

static VEvent *vevent_queue_head;
static VEvent *vevent_queue_tail;
static QemuMutex vevent_queue_lock;
static QemuCond vevent_queue_condition;

void vevent_queue_init(void)
{
    qemu_mutex_init(&vevent_queue_lock);
    qemu_cond_init(&vevent_queue_condition);
    vevent_queue_head = vevent_queue_tail = NULL;
}

void
vevent_queue_vevent(VEvent *vevent)
{
    vevent->next = NULL;
    qemu_mutex_lock(&vevent_queue_lock);
    if (vevent_queue_head) {
        assert(vevent_queue_tail);
        vevent_queue_tail->next = vevent;
    } else {
        vevent_queue_head = vevent;
    }
    vevent_queue_tail = vevent;
    qemu_cond_signal(&vevent_queue_condition);
    qemu_mutex_unlock(&vevent_queue_lock);
}

/* must have lock */
static VEvent *
vevent_dequeue_vevent(void)
{
    VEvent *vevent = NULL;
    if (vevent_queue_head) {
        vevent = vevent_queue_head;
        vevent_queue_head = vevent->next;
        vevent->next = NULL;
    }
    return vevent;
}

VEvent *vevent_wait_next_vevent(void)
{
    VEvent *vevent;

    qemu_mutex_lock(&vevent_queue_lock);
    while ((vevent = vevent_dequeue_vevent()) == NULL) {
        qemu_cond_wait(&vevent_queue_condition, &vevent_queue_lock);
    }
    qemu_mutex_unlock(&vevent_queue_lock);
    return vevent;
}

VEvent *vevent_get_next_vevent(void)
{
    VEvent *vevent;

    qemu_mutex_lock(&vevent_queue_lock);
    vevent = vevent_dequeue_vevent();
    qemu_mutex_unlock(&vevent_queue_lock);
    return vevent;
}