Statistics
| Branch: | Revision:

root / qemu-coroutine-lock.c @ 85e8dab1

History | View | Annotate | Download (4.4 kB)

1 b96e9247 Kevin Wolf
/*
2 b96e9247 Kevin Wolf
 * coroutine queues and locks
3 b96e9247 Kevin Wolf
 *
4 b96e9247 Kevin Wolf
 * Copyright (c) 2011 Kevin Wolf <kwolf@redhat.com>
5 b96e9247 Kevin Wolf
 *
6 b96e9247 Kevin Wolf
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 b96e9247 Kevin Wolf
 * of this software and associated documentation files (the "Software"), to deal
8 b96e9247 Kevin Wolf
 * in the Software without restriction, including without limitation the rights
9 b96e9247 Kevin Wolf
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 b96e9247 Kevin Wolf
 * copies of the Software, and to permit persons to whom the Software is
11 b96e9247 Kevin Wolf
 * furnished to do so, subject to the following conditions:
12 b96e9247 Kevin Wolf
 *
13 b96e9247 Kevin Wolf
 * The above copyright notice and this permission notice shall be included in
14 b96e9247 Kevin Wolf
 * all copies or substantial portions of the Software.
15 b96e9247 Kevin Wolf
 *
16 b96e9247 Kevin Wolf
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 b96e9247 Kevin Wolf
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 b96e9247 Kevin Wolf
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 b96e9247 Kevin Wolf
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 b96e9247 Kevin Wolf
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 b96e9247 Kevin Wolf
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 b96e9247 Kevin Wolf
 * THE SOFTWARE.
23 b96e9247 Kevin Wolf
 */
24 b96e9247 Kevin Wolf
25 b96e9247 Kevin Wolf
#include "qemu-common.h"
26 b96e9247 Kevin Wolf
#include "qemu-coroutine.h"
27 b96e9247 Kevin Wolf
#include "qemu-coroutine-int.h"
28 b96e9247 Kevin Wolf
#include "qemu-queue.h"
29 44a9b356 Paolo Bonzini
#include "main-loop.h"
30 b96e9247 Kevin Wolf
#include "trace.h"
31 b96e9247 Kevin Wolf
32 b96e9247 Kevin Wolf
static QTAILQ_HEAD(, Coroutine) unlock_bh_queue =
33 b96e9247 Kevin Wolf
    QTAILQ_HEAD_INITIALIZER(unlock_bh_queue);
34 e680cfa7 Kevin Wolf
static QEMUBH* unlock_bh;
35 b96e9247 Kevin Wolf
36 b96e9247 Kevin Wolf
static void qemu_co_queue_next_bh(void *opaque)
37 b96e9247 Kevin Wolf
{
38 b96e9247 Kevin Wolf
    Coroutine *next;
39 b96e9247 Kevin Wolf
40 b96e9247 Kevin Wolf
    trace_qemu_co_queue_next_bh();
41 b96e9247 Kevin Wolf
    while ((next = QTAILQ_FIRST(&unlock_bh_queue))) {
42 b96e9247 Kevin Wolf
        QTAILQ_REMOVE(&unlock_bh_queue, next, co_queue_next);
43 b96e9247 Kevin Wolf
        qemu_coroutine_enter(next, NULL);
44 b96e9247 Kevin Wolf
    }
45 b96e9247 Kevin Wolf
}
46 b96e9247 Kevin Wolf
47 b96e9247 Kevin Wolf
void qemu_co_queue_init(CoQueue *queue)
48 b96e9247 Kevin Wolf
{
49 b96e9247 Kevin Wolf
    QTAILQ_INIT(&queue->entries);
50 e680cfa7 Kevin Wolf
51 e680cfa7 Kevin Wolf
    if (!unlock_bh) {
52 e680cfa7 Kevin Wolf
        unlock_bh = qemu_bh_new(qemu_co_queue_next_bh, NULL);
53 e680cfa7 Kevin Wolf
    }
54 b96e9247 Kevin Wolf
}
55 b96e9247 Kevin Wolf
56 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
57 b96e9247 Kevin Wolf
{
58 b96e9247 Kevin Wolf
    Coroutine *self = qemu_coroutine_self();
59 b96e9247 Kevin Wolf
    QTAILQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
60 b96e9247 Kevin Wolf
    qemu_coroutine_yield();
61 b96e9247 Kevin Wolf
    assert(qemu_in_coroutine());
62 b96e9247 Kevin Wolf
}
63 b96e9247 Kevin Wolf
64 e9e6295b Zhi Yong Wu
void coroutine_fn qemu_co_queue_wait_insert_head(CoQueue *queue)
65 e9e6295b Zhi Yong Wu
{
66 e9e6295b Zhi Yong Wu
    Coroutine *self = qemu_coroutine_self();
67 e9e6295b Zhi Yong Wu
    QTAILQ_INSERT_HEAD(&queue->entries, self, co_queue_next);
68 e9e6295b Zhi Yong Wu
    qemu_coroutine_yield();
69 e9e6295b Zhi Yong Wu
    assert(qemu_in_coroutine());
70 e9e6295b Zhi Yong Wu
}
71 e9e6295b Zhi Yong Wu
72 b96e9247 Kevin Wolf
bool qemu_co_queue_next(CoQueue *queue)
73 b96e9247 Kevin Wolf
{
74 b96e9247 Kevin Wolf
    Coroutine *next;
75 b96e9247 Kevin Wolf
76 b96e9247 Kevin Wolf
    next = QTAILQ_FIRST(&queue->entries);
77 b96e9247 Kevin Wolf
    if (next) {
78 b96e9247 Kevin Wolf
        QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
79 b96e9247 Kevin Wolf
        QTAILQ_INSERT_TAIL(&unlock_bh_queue, next, co_queue_next);
80 b96e9247 Kevin Wolf
        trace_qemu_co_queue_next(next);
81 e680cfa7 Kevin Wolf
        qemu_bh_schedule(unlock_bh);
82 b96e9247 Kevin Wolf
    }
83 b96e9247 Kevin Wolf
84 b96e9247 Kevin Wolf
    return (next != NULL);
85 b96e9247 Kevin Wolf
}
86 b96e9247 Kevin Wolf
87 e8ee5e4c Stefan Hajnoczi
void qemu_co_queue_restart_all(CoQueue *queue)
88 e8ee5e4c Stefan Hajnoczi
{
89 e8ee5e4c Stefan Hajnoczi
    while (qemu_co_queue_next(queue)) {
90 e8ee5e4c Stefan Hajnoczi
        /* Do nothing */
91 e8ee5e4c Stefan Hajnoczi
    }
92 e8ee5e4c Stefan Hajnoczi
}
93 e8ee5e4c Stefan Hajnoczi
94 b96e9247 Kevin Wolf
bool qemu_co_queue_empty(CoQueue *queue)
95 b96e9247 Kevin Wolf
{
96 b96e9247 Kevin Wolf
    return (QTAILQ_FIRST(&queue->entries) == NULL);
97 b96e9247 Kevin Wolf
}
98 b96e9247 Kevin Wolf
99 b96e9247 Kevin Wolf
void qemu_co_mutex_init(CoMutex *mutex)
100 b96e9247 Kevin Wolf
{
101 b96e9247 Kevin Wolf
    memset(mutex, 0, sizeof(*mutex));
102 b96e9247 Kevin Wolf
    qemu_co_queue_init(&mutex->queue);
103 b96e9247 Kevin Wolf
}
104 b96e9247 Kevin Wolf
105 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
106 b96e9247 Kevin Wolf
{
107 b96e9247 Kevin Wolf
    Coroutine *self = qemu_coroutine_self();
108 b96e9247 Kevin Wolf
109 b96e9247 Kevin Wolf
    trace_qemu_co_mutex_lock_entry(mutex, self);
110 b96e9247 Kevin Wolf
111 b96e9247 Kevin Wolf
    while (mutex->locked) {
112 b96e9247 Kevin Wolf
        qemu_co_queue_wait(&mutex->queue);
113 b96e9247 Kevin Wolf
    }
114 b96e9247 Kevin Wolf
115 b96e9247 Kevin Wolf
    mutex->locked = true;
116 b96e9247 Kevin Wolf
117 b96e9247 Kevin Wolf
    trace_qemu_co_mutex_lock_return(mutex, self);
118 b96e9247 Kevin Wolf
}
119 b96e9247 Kevin Wolf
120 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
121 b96e9247 Kevin Wolf
{
122 b96e9247 Kevin Wolf
    Coroutine *self = qemu_coroutine_self();
123 b96e9247 Kevin Wolf
124 b96e9247 Kevin Wolf
    trace_qemu_co_mutex_unlock_entry(mutex, self);
125 b96e9247 Kevin Wolf
126 b96e9247 Kevin Wolf
    assert(mutex->locked == true);
127 b96e9247 Kevin Wolf
    assert(qemu_in_coroutine());
128 b96e9247 Kevin Wolf
129 b96e9247 Kevin Wolf
    mutex->locked = false;
130 b96e9247 Kevin Wolf
    qemu_co_queue_next(&mutex->queue);
131 b96e9247 Kevin Wolf
132 b96e9247 Kevin Wolf
    trace_qemu_co_mutex_unlock_return(mutex, self);
133 b96e9247 Kevin Wolf
}
134 12888904 Aneesh Kumar K.V
135 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_init(CoRwlock *lock)
136 12888904 Aneesh Kumar K.V
{
137 12888904 Aneesh Kumar K.V
    memset(lock, 0, sizeof(*lock));
138 12888904 Aneesh Kumar K.V
    qemu_co_queue_init(&lock->queue);
139 12888904 Aneesh Kumar K.V
}
140 12888904 Aneesh Kumar K.V
141 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_rdlock(CoRwlock *lock)
142 12888904 Aneesh Kumar K.V
{
143 12888904 Aneesh Kumar K.V
    while (lock->writer) {
144 12888904 Aneesh Kumar K.V
        qemu_co_queue_wait(&lock->queue);
145 12888904 Aneesh Kumar K.V
    }
146 12888904 Aneesh Kumar K.V
    lock->reader++;
147 12888904 Aneesh Kumar K.V
}
148 12888904 Aneesh Kumar K.V
149 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_unlock(CoRwlock *lock)
150 12888904 Aneesh Kumar K.V
{
151 12888904 Aneesh Kumar K.V
    assert(qemu_in_coroutine());
152 12888904 Aneesh Kumar K.V
    if (lock->writer) {
153 12888904 Aneesh Kumar K.V
        lock->writer = false;
154 e8ee5e4c Stefan Hajnoczi
        qemu_co_queue_restart_all(&lock->queue);
155 12888904 Aneesh Kumar K.V
    } else {
156 12888904 Aneesh Kumar K.V
        lock->reader--;
157 12888904 Aneesh Kumar K.V
        assert(lock->reader >= 0);
158 12888904 Aneesh Kumar K.V
        /* Wakeup only one waiting writer */
159 12888904 Aneesh Kumar K.V
        if (!lock->reader) {
160 12888904 Aneesh Kumar K.V
            qemu_co_queue_next(&lock->queue);
161 12888904 Aneesh Kumar K.V
        }
162 12888904 Aneesh Kumar K.V
    }
163 12888904 Aneesh Kumar K.V
}
164 12888904 Aneesh Kumar K.V
165 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_wrlock(CoRwlock *lock)
166 12888904 Aneesh Kumar K.V
{
167 12888904 Aneesh Kumar K.V
    while (lock->writer || lock->reader) {
168 12888904 Aneesh Kumar K.V
        qemu_co_queue_wait(&lock->queue);
169 12888904 Aneesh Kumar K.V
    }
170 12888904 Aneesh Kumar K.V
    lock->writer = true;
171 12888904 Aneesh Kumar K.V
}