2
* Copyright (c) 2009 Jakub Jermar
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* - Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
* - The name of the author may not be used to endorse or promote products
15
* derived from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
#include <fibril_sync.h>
42
void fibril_mutex_initialize(fibril_mutex_t *fm)
45
list_initialize(&fm->waiters);
48
void fibril_mutex_lock(fibril_mutex_t *fm)
50
futex_down(&async_futex);
51
if (fm->counter-- <= 0) {
52
fibril_t *f = (fibril_t *) fibril_get_id();
53
list_append(&f->link, &fm->waiters);
54
fibril_switch(FIBRIL_TO_MANAGER);
56
futex_up(&async_futex);
60
bool fibril_mutex_trylock(fibril_mutex_t *fm)
64
futex_down(&async_futex);
65
if (fm->counter > 0) {
69
futex_up(&async_futex);
74
static void _fibril_mutex_unlock_unsafe(fibril_mutex_t *fm)
76
assert(fm->counter <= 0);
77
if (fm->counter++ < 0) {
81
assert(!list_empty(&fm->waiters));
82
tmp = fm->waiters.next;
83
f = list_get_instance(tmp, fibril_t, link);
84
list_remove(&f->link);
85
fibril_add_ready((fid_t) f);
89
void fibril_mutex_unlock(fibril_mutex_t *fm)
91
futex_down(&async_futex);
92
_fibril_mutex_unlock_unsafe(fm);
93
futex_up(&async_futex);
96
void fibril_rwlock_initialize(fibril_rwlock_t *frw)
100
list_initialize(&frw->waiters);
103
void fibril_rwlock_read_lock(fibril_rwlock_t *frw)
105
futex_down(&async_futex);
107
fibril_t *f = (fibril_t *) fibril_get_id();
108
f->flags &= ~FIBRIL_WRITER;
109
list_append(&f->link, &frw->waiters);
110
fibril_switch(FIBRIL_TO_MANAGER);
113
futex_up(&async_futex);
117
void fibril_rwlock_write_lock(fibril_rwlock_t *frw)
119
futex_down(&async_futex);
120
if (frw->writers || frw->readers) {
121
fibril_t *f = (fibril_t *) fibril_get_id();
122
f->flags |= FIBRIL_WRITER;
123
list_append(&f->link, &frw->waiters);
124
fibril_switch(FIBRIL_TO_MANAGER);
127
futex_up(&async_futex);
131
static void _fibril_rwlock_common_unlock(fibril_rwlock_t *frw)
133
futex_down(&async_futex);
134
assert(frw->readers || (frw->writers == 1));
142
assert(!frw->readers && !frw->writers);
144
while (!list_empty(&frw->waiters)) {
145
link_t *tmp = frw->waiters.next;
146
fibril_t *f = list_get_instance(tmp, fibril_t, link);
148
if (f->flags & FIBRIL_WRITER) {
151
list_remove(&f->link);
152
fibril_add_ready((fid_t) f);
156
list_remove(&f->link);
157
fibril_add_ready((fid_t) f);
162
futex_up(&async_futex);
165
void fibril_rwlock_read_unlock(fibril_rwlock_t *frw)
167
_fibril_rwlock_common_unlock(frw);
170
void fibril_rwlock_write_unlock(fibril_rwlock_t *frw)
172
_fibril_rwlock_common_unlock(frw);
175
void fibril_condvar_initialize(fibril_condvar_t *fcv)
177
list_initialize(&fcv->waiters);
180
void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
182
fibril_t *f = (fibril_t *) fibril_get_id();
184
futex_down(&async_futex);
185
list_append(&f->link, &fcv->waiters);
186
_fibril_mutex_unlock_unsafe(fm);
187
fibril_switch(FIBRIL_TO_MANAGER);
188
fibril_mutex_lock(fm);
191
static void _fibril_condvar_wakeup_common(fibril_condvar_t *fcv, bool once)
196
futex_down(&async_futex);
197
while (!list_empty(&fcv->waiters)) {
198
tmp = fcv->waiters.next;
199
f = list_get_instance(tmp, fibril_t, link);
200
list_remove(&f->link);
201
fibril_add_ready((fid_t) f);
205
futex_up(&async_futex);
208
void fibril_condvar_signal(fibril_condvar_t *fcv)
210
_fibril_condvar_wakeup_common(fcv, true);
213
void fibril_condvar_broadcast(fibril_condvar_t *fcv)
215
_fibril_condvar_wakeup_common(fcv, false);