Statistics
| Branch: | Revision:

root / qemu-coroutine-lock.c @ feature-archipelago

History | View | Annotate | Download (4.8 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 737e150e Paolo Bonzini
#include "block/coroutine.h"
27 737e150e Paolo Bonzini
#include "block/coroutine_int.h"
28 1de7afc9 Paolo Bonzini
#include "qemu/queue.h"
29 b96e9247 Kevin Wolf
#include "trace.h"
30 b96e9247 Kevin Wolf
31 b96e9247 Kevin Wolf
void qemu_co_queue_init(CoQueue *queue)
32 b96e9247 Kevin Wolf
{
33 b96e9247 Kevin Wolf
    QTAILQ_INIT(&queue->entries);
34 b96e9247 Kevin Wolf
}
35 b96e9247 Kevin Wolf
36 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
37 b96e9247 Kevin Wolf
{
38 b96e9247 Kevin Wolf
    Coroutine *self = qemu_coroutine_self();
39 b96e9247 Kevin Wolf
    QTAILQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
40 b96e9247 Kevin Wolf
    qemu_coroutine_yield();
41 b96e9247 Kevin Wolf
    assert(qemu_in_coroutine());
42 b96e9247 Kevin Wolf
}
43 b96e9247 Kevin Wolf
44 02ffb504 Stefan Hajnoczi
/**
45 02ffb504 Stefan Hajnoczi
 * qemu_co_queue_run_restart:
46 02ffb504 Stefan Hajnoczi
 *
47 02ffb504 Stefan Hajnoczi
 * Enter each coroutine that was previously marked for restart by
48 02ffb504 Stefan Hajnoczi
 * qemu_co_queue_next() or qemu_co_queue_restart_all().  This function is
49 02ffb504 Stefan Hajnoczi
 * invoked by the core coroutine code when the current coroutine yields or
50 02ffb504 Stefan Hajnoczi
 * terminates.
51 02ffb504 Stefan Hajnoczi
 */
52 02ffb504 Stefan Hajnoczi
void qemu_co_queue_run_restart(Coroutine *co)
53 02ffb504 Stefan Hajnoczi
{
54 02ffb504 Stefan Hajnoczi
    Coroutine *next;
55 02ffb504 Stefan Hajnoczi
56 02ffb504 Stefan Hajnoczi
    trace_qemu_co_queue_run_restart(co);
57 02ffb504 Stefan Hajnoczi
    while ((next = QTAILQ_FIRST(&co->co_queue_wakeup))) {
58 02ffb504 Stefan Hajnoczi
        QTAILQ_REMOVE(&co->co_queue_wakeup, next, co_queue_next);
59 02ffb504 Stefan Hajnoczi
        qemu_coroutine_enter(next, NULL);
60 02ffb504 Stefan Hajnoczi
    }
61 02ffb504 Stefan Hajnoczi
}
62 02ffb504 Stefan Hajnoczi
63 28f08246 Stefan Hajnoczi
static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)
64 b96e9247 Kevin Wolf
{
65 02ffb504 Stefan Hajnoczi
    Coroutine *self = qemu_coroutine_self();
66 b96e9247 Kevin Wolf
    Coroutine *next;
67 28f08246 Stefan Hajnoczi
68 28f08246 Stefan Hajnoczi
    if (QTAILQ_EMPTY(&queue->entries)) {
69 28f08246 Stefan Hajnoczi
        return false;
70 28f08246 Stefan Hajnoczi
    }
71 b96e9247 Kevin Wolf
72 28f08246 Stefan Hajnoczi
    while ((next = QTAILQ_FIRST(&queue->entries)) != NULL) {
73 b96e9247 Kevin Wolf
        QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
74 02ffb504 Stefan Hajnoczi
        QTAILQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next);
75 b96e9247 Kevin Wolf
        trace_qemu_co_queue_next(next);
76 28f08246 Stefan Hajnoczi
        if (single) {
77 28f08246 Stefan Hajnoczi
            break;
78 28f08246 Stefan Hajnoczi
        }
79 b96e9247 Kevin Wolf
    }
80 28f08246 Stefan Hajnoczi
    return true;
81 28f08246 Stefan Hajnoczi
}
82 b96e9247 Kevin Wolf
83 b681a1c7 Benoît Canet
bool coroutine_fn qemu_co_queue_next(CoQueue *queue)
84 28f08246 Stefan Hajnoczi
{
85 b681a1c7 Benoît Canet
    assert(qemu_in_coroutine());
86 28f08246 Stefan Hajnoczi
    return qemu_co_queue_do_restart(queue, true);
87 b96e9247 Kevin Wolf
}
88 b96e9247 Kevin Wolf
89 b681a1c7 Benoît Canet
void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue)
90 e8ee5e4c Stefan Hajnoczi
{
91 b681a1c7 Benoît Canet
    assert(qemu_in_coroutine());
92 28f08246 Stefan Hajnoczi
    qemu_co_queue_do_restart(queue, false);
93 e8ee5e4c Stefan Hajnoczi
}
94 e8ee5e4c Stefan Hajnoczi
95 b681a1c7 Benoît Canet
bool qemu_co_enter_next(CoQueue *queue)
96 b681a1c7 Benoît Canet
{
97 b681a1c7 Benoît Canet
    Coroutine *next;
98 b681a1c7 Benoît Canet
99 b681a1c7 Benoît Canet
    next = QTAILQ_FIRST(&queue->entries);
100 b681a1c7 Benoît Canet
    if (!next) {
101 b681a1c7 Benoît Canet
        return false;
102 b681a1c7 Benoît Canet
    }
103 b681a1c7 Benoît Canet
104 b681a1c7 Benoît Canet
    QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
105 b681a1c7 Benoît Canet
    qemu_coroutine_enter(next, NULL);
106 b681a1c7 Benoît Canet
    return true;
107 b681a1c7 Benoît Canet
}
108 b681a1c7 Benoît Canet
109 b96e9247 Kevin Wolf
bool qemu_co_queue_empty(CoQueue *queue)
110 b96e9247 Kevin Wolf
{
111 b96e9247 Kevin Wolf
    return (QTAILQ_FIRST(&queue->entries) == NULL);
112 b96e9247 Kevin Wolf
}
113 b96e9247 Kevin Wolf
114 b96e9247 Kevin Wolf
void qemu_co_mutex_init(CoMutex *mutex)
115 b96e9247 Kevin Wolf
{
116 b96e9247 Kevin Wolf
    memset(mutex, 0, sizeof(*mutex));
117 b96e9247 Kevin Wolf
    qemu_co_queue_init(&mutex->queue);
118 b96e9247 Kevin Wolf
}
119 b96e9247 Kevin Wolf
120 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_mutex_lock(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_lock_entry(mutex, self);
125 b96e9247 Kevin Wolf
126 b96e9247 Kevin Wolf
    while (mutex->locked) {
127 b96e9247 Kevin Wolf
        qemu_co_queue_wait(&mutex->queue);
128 b96e9247 Kevin Wolf
    }
129 b96e9247 Kevin Wolf
130 b96e9247 Kevin Wolf
    mutex->locked = true;
131 b96e9247 Kevin Wolf
132 b96e9247 Kevin Wolf
    trace_qemu_co_mutex_lock_return(mutex, self);
133 b96e9247 Kevin Wolf
}
134 b96e9247 Kevin Wolf
135 b96e9247 Kevin Wolf
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
136 b96e9247 Kevin Wolf
{
137 b96e9247 Kevin Wolf
    Coroutine *self = qemu_coroutine_self();
138 b96e9247 Kevin Wolf
139 b96e9247 Kevin Wolf
    trace_qemu_co_mutex_unlock_entry(mutex, self);
140 b96e9247 Kevin Wolf
141 b96e9247 Kevin Wolf
    assert(mutex->locked == true);
142 b96e9247 Kevin Wolf
    assert(qemu_in_coroutine());
143 b96e9247 Kevin Wolf
144 b96e9247 Kevin Wolf
    mutex->locked = false;
145 b96e9247 Kevin Wolf
    qemu_co_queue_next(&mutex->queue);
146 b96e9247 Kevin Wolf
147 b96e9247 Kevin Wolf
    trace_qemu_co_mutex_unlock_return(mutex, self);
148 b96e9247 Kevin Wolf
}
149 12888904 Aneesh Kumar K.V
150 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_init(CoRwlock *lock)
151 12888904 Aneesh Kumar K.V
{
152 12888904 Aneesh Kumar K.V
    memset(lock, 0, sizeof(*lock));
153 12888904 Aneesh Kumar K.V
    qemu_co_queue_init(&lock->queue);
154 12888904 Aneesh Kumar K.V
}
155 12888904 Aneesh Kumar K.V
156 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_rdlock(CoRwlock *lock)
157 12888904 Aneesh Kumar K.V
{
158 12888904 Aneesh Kumar K.V
    while (lock->writer) {
159 12888904 Aneesh Kumar K.V
        qemu_co_queue_wait(&lock->queue);
160 12888904 Aneesh Kumar K.V
    }
161 12888904 Aneesh Kumar K.V
    lock->reader++;
162 12888904 Aneesh Kumar K.V
}
163 12888904 Aneesh Kumar K.V
164 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_unlock(CoRwlock *lock)
165 12888904 Aneesh Kumar K.V
{
166 12888904 Aneesh Kumar K.V
    assert(qemu_in_coroutine());
167 12888904 Aneesh Kumar K.V
    if (lock->writer) {
168 12888904 Aneesh Kumar K.V
        lock->writer = false;
169 e8ee5e4c Stefan Hajnoczi
        qemu_co_queue_restart_all(&lock->queue);
170 12888904 Aneesh Kumar K.V
    } else {
171 12888904 Aneesh Kumar K.V
        lock->reader--;
172 12888904 Aneesh Kumar K.V
        assert(lock->reader >= 0);
173 12888904 Aneesh Kumar K.V
        /* Wakeup only one waiting writer */
174 12888904 Aneesh Kumar K.V
        if (!lock->reader) {
175 12888904 Aneesh Kumar K.V
            qemu_co_queue_next(&lock->queue);
176 12888904 Aneesh Kumar K.V
        }
177 12888904 Aneesh Kumar K.V
    }
178 12888904 Aneesh Kumar K.V
}
179 12888904 Aneesh Kumar K.V
180 12888904 Aneesh Kumar K.V
void qemu_co_rwlock_wrlock(CoRwlock *lock)
181 12888904 Aneesh Kumar K.V
{
182 12888904 Aneesh Kumar K.V
    while (lock->writer || lock->reader) {
183 12888904 Aneesh Kumar K.V
        qemu_co_queue_wait(&lock->queue);
184 12888904 Aneesh Kumar K.V
    }
185 12888904 Aneesh Kumar K.V
    lock->writer = true;
186 12888904 Aneesh Kumar K.V
}