source: mainline/uspace/lib/c/include/fibril_synch.h@ d4b7b29

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d4b7b29 was 2965d18, checked in by Jiří Zárevúcky <jiri.zarevucky@…>, 7 years ago

Add debug counter for rmutex locks.

  • Property mode set to 100644
File size: 7.8 KB
RevLine 
[f3afd24]1/*
[1b20da0]2 * Copyright (c) 2009 Jakub Jermar
[f3afd24]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
33 */
34
[1e4cada]35#ifndef LIBC_FIBRIL_SYNCH_H_
36#define LIBC_FIBRIL_SYNCH_H_
[f3afd24]37
38#include <fibril.h>
39#include <adt/list.h>
[0b05082]40#include <tls.h>
[cadfa8e]41#include <sys/time.h>
[3e6a98c5]42#include <stdbool.h>
[c124c985]43#include <futex.h>
44
45/**
46 * "Restricted" fibril mutex.
47 *
48 * Similar to `fibril_mutex_t`, but has a set of restrictions placed on its
49 * use. Within a rmutex critical section, you
50 * - may not use any other synchronization primitive,
51 * save for another `fibril_rmutex_t`. This includes nonblocking
52 * operations like cvar signal and mutex unlock.
53 * - may not read IPC messages
54 * - may not start a new thread/fibril
55 * (creating fibril without starting is fine)
56 *
57 * Additionally, locking with a timeout is not possible on this mutex,
58 * and there is no associated condition variable type.
59 * This is a design constraint, not a lack of implementation effort.
60 */
61typedef struct {
62 // TODO: At this point, this is just silly handwaving to hide current
63 // futex use behind a fibril based abstraction. Later, the imple-
64 // mentation will change, but the restrictions placed on this type
65 // will allow it to be simpler and faster than a regular mutex.
66 // There might also be optional debug checking of the assumptions.
67 //
68 // Note that a consequence of the restrictions is that if we are
69 // running on a single thread, no other fibril can ever get to run
70 // while a fibril has a rmutex locked. That means that for
71 // single-threaded programs, we can reduce all rmutex locks and
72 // unlocks to simple branches on a global bool variable.
73
74 futex_t futex;
75} fibril_rmutex_t;
76
77#define FIBRIL_RMUTEX_INITIALIZER(name) \
78 { .futex = FUTEX_INITIALIZE(1) }
79
80#define FIBRIL_RMUTEX_INITIALIZE(name) \
81 fibril_rmutex_t name = FIBRIL_RMUTEX_INITIALIZER(name)
82
[668f8cbf]83typedef struct {
[d161715]84 fibril_owner_info_t oi; /**< Keep this the first thing. */
[f3afd24]85 int counter;
[b72efe8]86 list_t waiters;
[f3afd24]87} fibril_mutex_t;
88
[e9460aa]89#define FIBRIL_MUTEX_INITIALIZER(name) \
90 { \
[668f8cbf]91 .oi = { \
92 .owned_by = NULL \
93 }, \
[f3afd24]94 .counter = 1, \
95 .waiters = { \
[b72efe8]96 .head = { \
97 .prev = &(name).waiters.head, \
98 .next = &(name).waiters.head, \
99 } \
[f3afd24]100 } \
101 }
[a35b458]102
[e9460aa]103#define FIBRIL_MUTEX_INITIALIZE(name) \
[1b20da0]104 fibril_mutex_t name = FIBRIL_MUTEX_INITIALIZER(name)
[f3afd24]105
106typedef struct {
[d161715]107 fibril_owner_info_t oi; /**< Keep this the first thing. */
[fb0ec570]108 unsigned int writers;
109 unsigned int readers;
[b72efe8]110 list_t waiters;
[f3afd24]111} fibril_rwlock_t;
112
[e9460aa]113#define FIBRIL_RWLOCK_INITIALIZER(name) \
114 { \
[668f8cbf]115 .oi = { \
116 .owned_by = NULL \
117 }, \
[92d34f0b]118 .readers = 0, \
119 .writers = 0, \
120 .waiters = { \
[b72efe8]121 .head = { \
122 .prev = &(name).waiters.head, \
123 .next = &(name).waiters.head, \
124 } \
[f3afd24]125 } \
126 }
127
[e9460aa]128#define FIBRIL_RWLOCK_INITIALIZE(name) \
129 fibril_rwlock_t name = FIBRIL_RWLOCK_INITIALIZER(name)
130
[9ae22ba]131typedef struct {
[b72efe8]132 list_t waiters;
[9ae22ba]133} fibril_condvar_t;
134
[e9460aa]135#define FIBRIL_CONDVAR_INITIALIZER(name) \
136 { \
[c51a7cd]137 .waiters = { \
[b72efe8]138 .head = { \
139 .next = &(name).waiters.head, \
140 .prev = &(name).waiters.head, \
141 } \
[c51a7cd]142 } \
143 }
144
[e9460aa]145#define FIBRIL_CONDVAR_INITIALIZE(name) \
146 fibril_condvar_t name = FIBRIL_CONDVAR_INITIALIZER(name)
147
[2a3214e]148typedef void (*fibril_timer_fun_t)(void *);
149
150typedef enum {
151 /** Timer has not been set or has been cleared */
152 fts_not_set,
153 /** Timer was set but did not fire yet */
154 fts_active,
155 /** Timer has fired and has not been cleared since */
156 fts_fired,
[53f68fd]157 /** Timer fibril is requested to terminate */
158 fts_cleanup,
159 /** Timer fibril acknowledged termination */
160 fts_clean
[2a3214e]161} fibril_timer_state_t;
162
163/** Fibril timer.
164 *
165 * When a timer is set it executes a callback function (in a separate
166 * fibril) after a specified time interval. The timer can be cleared
167 * (canceled) before that. From the return value of fibril_timer_clear()
168 * one can tell whether the timer fired or not.
169 */
170typedef struct {
171 fibril_mutex_t lock;
[78192cc7]172 fibril_mutex_t *lockp;
[2a3214e]173 fibril_condvar_t cv;
174 fid_t fibril;
175 fibril_timer_state_t state;
[7c15d6f]176 /** FID of fibril executing handler or 0 if handler is not running */
177 fid_t handler_fid;
[2a3214e]178
179 suseconds_t delay;
180 fibril_timer_fun_t fun;
181 void *arg;
182} fibril_timer_t;
183
[a55d76b1]184/** A counting semaphore for fibrils. */
185typedef struct {
[fb0ec570]186 long int count;
[a55d76b1]187 list_t waiters;
188} fibril_semaphore_t;
189
190#define FIBRIL_SEMAPHORE_INITIALIZER(name, cnt) \
191 { \
192 .count = (cnt), \
193 .waiters = { \
194 .head = { \
195 .next = &(name).waiters.head, \
196 .prev = &(name).waiters.head, \
197 } \
198 } \
199 }
200
201#define FIBRIL_SEMAPHORE_INITIALIZE(name, cnt) \
202 fibril_semaphore_t name = FIBRIL_SEMAPHORE_INITIALIZER(name, cnt)
203
[2965d18]204extern void fibril_rmutex_initialize(fibril_rmutex_t *);
205extern void fibril_rmutex_lock(fibril_rmutex_t *);
206extern bool fibril_rmutex_trylock(fibril_rmutex_t *);
207extern void fibril_rmutex_unlock(fibril_rmutex_t *);
208
[f3afd24]209extern void fibril_mutex_initialize(fibril_mutex_t *);
210extern void fibril_mutex_lock(fibril_mutex_t *);
211extern bool fibril_mutex_trylock(fibril_mutex_t *);
212extern void fibril_mutex_unlock(fibril_mutex_t *);
[b0a76d5]213extern bool fibril_mutex_is_locked(fibril_mutex_t *);
[f3afd24]214
215extern void fibril_rwlock_initialize(fibril_rwlock_t *);
216extern void fibril_rwlock_read_lock(fibril_rwlock_t *);
217extern void fibril_rwlock_write_lock(fibril_rwlock_t *);
218extern void fibril_rwlock_read_unlock(fibril_rwlock_t *);
219extern void fibril_rwlock_write_unlock(fibril_rwlock_t *);
[b0a76d5]220extern bool fibril_rwlock_is_read_locked(fibril_rwlock_t *);
221extern bool fibril_rwlock_is_write_locked(fibril_rwlock_t *);
[c81b6f2]222extern bool fibril_rwlock_is_locked(fibril_rwlock_t *);
[f3afd24]223
[9ae22ba]224extern void fibril_condvar_initialize(fibril_condvar_t *);
[b7fd2a0]225extern errno_t fibril_condvar_wait_timeout(fibril_condvar_t *, fibril_mutex_t *,
[cadfa8e]226 suseconds_t);
[9ae22ba]227extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *);
228extern void fibril_condvar_signal(fibril_condvar_t *);
229extern void fibril_condvar_broadcast(fibril_condvar_t *);
230
[78192cc7]231extern fibril_timer_t *fibril_timer_create(fibril_mutex_t *);
[2a3214e]232extern void fibril_timer_destroy(fibril_timer_t *);
233extern void fibril_timer_set(fibril_timer_t *, suseconds_t, fibril_timer_fun_t,
234 void *);
[78192cc7]235extern void fibril_timer_set_locked(fibril_timer_t *, suseconds_t,
236 fibril_timer_fun_t, void *);
[2a3214e]237extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *);
[78192cc7]238extern fibril_timer_state_t fibril_timer_clear_locked(fibril_timer_t *);
[2a3214e]239
[a55d76b1]240extern void fibril_semaphore_initialize(fibril_semaphore_t *, long);
241extern void fibril_semaphore_up(fibril_semaphore_t *);
242extern void fibril_semaphore_down(fibril_semaphore_t *);
243
[f3afd24]244#endif
245
246/** @}
247 */
Note: See TracBrowser for help on using the repository browser.