KallistiOS
2.0.0
Main Page
Modules
Data Structures
Files
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
include
kos
rwsem.h
Go to the documentation of this file.
1
/* KallistiOS 2.0.0
2
3
include/kos/rwsem.h
4
Copyright (C) 2008, 2010, 2012 Lawrence Sebald
5
6
*/
7
8
/** \file kos/rwsem.h
9
\brief Definition for a reader/writer semaphore.
10
11
This file defines a concept of reader/writer semaphores. Basically, this
12
type of lock allows an unlimited number of "readers" to acquire the lock at
13
a time, but only one "writer" (and only if no readers hold the lock).
14
Readers, by definition, should not change any global data (since they are
15
defined to only be reading), and since this is the case it is safe to allow
16
multiple readers to access global data that is shared amongst threads.
17
Writers on the other hand require exclusive access since they will be
18
changing global data in the critical section, and they cannot share with
19
a reader either (since the reader might attempt to read while the writer is
20
changing data).
21
22
\author Lawrence Sebald
23
*/
24
25
#ifndef __KOS_RWSEM_H
26
#define __KOS_RWSEM_H
27
28
#include <sys/cdefs.h>
29
30
__BEGIN_DECLS
31
32
#include <stddef.h>
33
#include <
kos/thread.h
>
34
35
/** \brief Reader/writer semaphore structure.
36
37
All members of this structure should be considered to be private, it is not
38
safe to change anything in here yourself.
39
40
\headerfile kos/rwsem.h
41
*/
42
typedef
struct
rw_semaphore
{
43
/** \brief Are we initialized? */
44
int
initialized
;
45
46
/** \brief The number of readers that are currently holding the lock. */
47
int
read_count
;
48
49
/** \brief The thread holding the write lock. */
50
kthread_t
*
write_lock
;
51
52
/** \brief Space for one reader who's trying to upgrade to a writer. */
53
kthread_t
*
reader_waiting
;
54
}
rw_semaphore_t
;
55
56
/** \brief Initializer for a transient reader/writer semaphore */
57
#define RWSEM_INITIALIZER { 1, 0, NULL, NULL }
58
59
/** \brief Allocate a reader/writer semaphore.
60
61
This function allocates a new reader/writer lock that is initially not
62
locked either for reading or writing.
63
64
This function is formally deprecated, and should not be used in newly
65
written code. Instead, please use rwsem_init().
66
67
\return The created semaphore, or NULL on failure (errno will be set as
68
appropriate).
69
70
\par Error Conditions:
71
\em ENOMEM - out of memory
72
*/
73
rw_semaphore_t
*
rwsem_create
() __attribute__((deprecated));
74
75
/** \brief Initialize a reader/writer semaphore.
76
77
This function initializes a new reader/writer semaphore for use.
78
79
\retval 0 On success (no error conditions currently defined).
80
*/
81
int
rwsem_init
(
rw_semaphore_t
*s);
82
83
/** \brief Destroy a reader/writer semaphore.
84
85
This function cleans up a reader/writer semaphore. It is an error to attempt
86
to destroy a r/w semaphore that is locked either for reading or writing.
87
88
\param s The r/w semaphore to destroy.
89
\retval 0 On success.
90
\retval -1 On error, errno will be set as appropriate.
91
92
\par Error Conditions:
93
\em EBUSY - the semaphore is still locked
94
*/
95
int
rwsem_destroy
(
rw_semaphore_t
*s);
96
97
/** \brief Lock a reader/writer semaphore for reading (with a timeout).
98
99
This function attempts to lock the r/w semaphore for reading. If the
100
semaphore is locked for writing, this function will block until it is
101
possible to obtain the lock for reading or the timeout expires. This
102
function is <b>NOT</b> safe to call inside of an interrupt.
103
104
\param s The r/w semaphore to lock.
105
\param timeout The maximum time to wait (in milliseconds).
106
\retval 0 On success
107
\retval -1 On error, errno will be set as appropriate.
108
109
\par Error Conditions:
110
\em EPERM - called inside an interrupt \n
111
\em ETIMEDOUT - the timeout expires before the lock can be acquired \n
112
\em EINVAL - the timeout value is invalid \n
113
\em EINVAL - the semaphore is not initialized
114
*/
115
int
rwsem_read_lock_timed
(
rw_semaphore_t
*s,
int
timeout);
116
117
/** \brief Lock a reader/writer semaphore for reading.
118
119
This function attempts to lock the r/w semaphore for reading. If the
120
semaphore is locked for writing, this function will block until it is
121
possible to obtain the lock for reading. This function is <b>NOT</b> safe to
122
call inside of an interrupt.
123
124
\param s The r/w semaphore to lock.
125
\retval 0 On success
126
\retval -1 On error, errno will be set as appropriate.
127
128
\par Error Conditions:
129
\em EPERM - called inside an interrupt \n
130
\em EINVAL - the semaphore is not initialized
131
*/
132
int
rwsem_read_lock
(
rw_semaphore_t
*s);
133
134
/** \brief Lock a reader/writer semaphore for writing (with a timeout).
135
136
This function attempts to lock the r/w semaphore for writing. If the
137
semaphore is locked for reading or writing, this function will block until
138
it is possible to obtain the lock for writing or the timeout expires. This
139
function is <b>NOT</b> safe to call inside of an interrupt.
140
141
\param s The r/w semaphore to lock.
142
\param timeout The maximum time to wait (in milliseconds).
143
\retval 0 On success.
144
\retval -1 On error, errno will be set as appropriate.
145
146
\par Error Conditions:
147
\em EPERM - called inside an interrupt \n
148
\em ETIMEDOUT - the timeout expires before the lock can be acquired \n
149
\em EINVAL - the timeout value is invalid \n
150
\em EINVAL - the semaphore is not initialized
151
*/
152
int
rwsem_write_lock_timed
(
rw_semaphore_t
*s,
int
timeout);
153
154
/** \brief Lock a reader/writer semaphore for writing.
155
156
This function attempts to lock the r/w semaphore for writing. If the
157
semaphore is locked for reading or writing, this function will block until
158
it is possible to obtain the lock for writing. This function is <b>NOT</b>
159
safe to call inside of an interrupt.
160
161
\param s The r/w semaphore to lock.
162
\retval 0 On success.
163
\retval -1 On error, errno will be set as appropriate.
164
165
\par Error conditions:
166
\em EPERM - called inside an interrupt \n
167
\em EINVAL - the semaphore is not initialized
168
*/
169
int
rwsem_write_lock
(
rw_semaphore_t
*s);
170
171
/** \brief Unlock a reader/writer semaphore from a read lock.
172
173
This function releases one instance of the read lock on the r/w semaphore.
174
175
\param s The r/w semaphore to release the read lock on.
176
\retval 0 On success.
177
\retval -1 On error, errno will be set as appropriate.
178
179
\par Error Conditions:
180
\em EPERM - the read lock is not currently held \n
181
\em EINVAL - the semaphore is not initialized
182
*/
183
int
rwsem_read_unlock
(
rw_semaphore_t
*s);
184
185
/** \brief Unlock a reader/writer semaphore from a write lock.
186
187
This function releases one instance of the write lock on the r/w semaphore.
188
189
\param s The r/w semaphore to release the write lock on.
190
\retval 0 On success.
191
\retval -1 On error, errno will be set as appropriate.
192
193
\par Error Conditions:
194
\em EPERM - the write lock is not currently held by the calling
195
thread \n
196
\em EINVAL - the semaphore is not initialized
197
*/
198
int
rwsem_write_unlock
(
rw_semaphore_t
*s);
199
200
/** \brief Unlock a reader/writer semaphore.
201
202
This function releases the lock held by the current thread on the specified
203
reader/writer semaphore. This function will automatically determine which
204
lock is held by the calling thread and release it as appropriate.
205
206
This function is <b>NOT</b> safe to call (in general) if you do not hold the
207
lock!
208
209
\param s The r/w semaphore to release the lock on.
210
\retval 0 On success.
211
\retval -1 On error, errno will be set as appropriate.
212
213
\par Error Conditions:
214
\em EPERM - the lock is not currently held by the calling thread \n
215
\em EINVAL - the semaphore is not initialized
216
*/
217
int
rwsem_unlock
(
rw_semaphore_t
*s);
218
219
/** \brief Attempt to lock a reader/writer semaphore for reading.
220
221
This function attempts to lock the r/w semaphore for reading. If for any
222
reason rwsem_read_lock would normally block, this function will return an
223
error. This function is safe to call inside an interrupt.
224
225
\param s The r/w semaphore to attempt to lock.
226
\retval 0 On success.
227
\retval -1 On error, errno will be set as appropriate.
228
229
\par Error Conditions:
230
\em EWOULDBLOCK - a call to rwsem_read_lock would block \n
231
\em EINVAL - the semaphore is not initialized
232
*/
233
int
rwsem_read_trylock
(
rw_semaphore_t
*s);
234
235
/** \brief Attempt to lock a reader/writer semaphore for writing.
236
237
This function attempts to lock the r/w semaphore for writing. If for any
238
reason rwsem_write_lock would normally block, this function will return an
239
error. This function is safe to call inside an interrupt.
240
241
\param s The r/w semaphore to attempt to lock.
242
\retval 0 On success.
243
\retval -1 On error, errno will be set as appropriate.
244
245
\par Error Conditions:
246
\em EWOULDBLOCK - a call to rwsem_write_lock would block \n
247
\em EINVAL - the semaphore is not initialized
248
*/
249
int
rwsem_write_trylock
(
rw_semaphore_t
*s);
250
251
/** \brief Upgrade a thread from reader status to writer status (with a
252
timeout).
253
254
This function will upgrade the lock on the calling thread from a reader
255
state to a writer state. If it cannot do this at the moment, it will block
256
until it is possible. This function is <b>NOT</b> safe to call inside an
257
interrupt.
258
259
You can only have one reader waiting to upgrade at a time, otherwise the
260
state would potentially become corrupted between when this is called and
261
when you get the lock. If you get -1 back from this, you must not assume
262
that you can write safely! On error, the calling thread will still hold a
263
read lock.
264
265
\param s The r/w semaphore to upgrade.
266
\param timeout The maximum time to wait (in milliseconds).
267
\retval 0 On success.
268
\retval -1 On error, errno will be set as appropriate.
269
270
\par Error Conditions:
271
\em EPERM - called inside an interrupt \n
272
\em EINVAL - the semaphore is not initialized \n
273
\em EINVAL - the timeout value is invalid \n
274
\em EBUSY - another reader has already requested an upgrade \n
275
\em ETIMEDOUT - the timeout expired before the write lock could be
276
acquired
277
*/
278
int
rwsem_read_upgrade_timed
(
rw_semaphore_t
*s,
int
timeout);
279
280
/** \brief Upgrade a thread from reader status to writer status.
281
282
This function will upgrade the lock on the calling thread from a reader
283
state to a writer state. If it cannot do this at the moment, it will block
284
until it is possible. This function is <b>NOT</b> safe to call inside an
285
interrupt.
286
287
You can only have one reader waiting to upgrade at a time, otherwise the
288
state would potentially become corrupted between when this is called and
289
when you get the lock. If you get -1 back from this, you must not assume
290
that you can write safely! On error, the calling thread will still hold a
291
read lock.
292
293
\param s The r/w semaphore to upgrade.
294
\retval 0 On success.
295
\retval -1 On error, errno will be set as appropriate.
296
297
\par Error Conditions:
298
\em EPERM - called inside an interrupt \n
299
\em EINVAL - the semaphore is not initialized \n
300
\em EBUSY - another reader has already requested an upgrade
301
*/
302
int
rwsem_read_upgrade
(
rw_semaphore_t
*s);
303
304
/** \brief Attempt to upgrade a thread from reader status to writer status.
305
306
This function will attempt to upgrade the lock on the calling thread to
307
writer status. If for any reason rwsem_read_upgrade would block, this
308
function will return an error. This function is safe to call inside an
309
interrupt. Note that on error, the read lock is still held!
310
311
\param s The r/w semaphore to upgrade.
312
\retval 0 On success.
313
\retval -1 On error, errno will be set as appropriate.
314
315
\par Error Conditions:
316
\em EWOULDBLOCK - a call to rwsem_read_upgrade would block \n
317
\em EBUSY - another reader has already requested an upgrade \n
318
\em EINVAL - the sempahore is not initialized
319
*/
320
int
rwsem_read_tryupgrade
(
rw_semaphore_t
*s);
321
322
/** \brief Read the reader count on the reader/writer semaphore.
323
324
This function is not a safe way to see if the lock will be locked by any
325
readers when you get around to locking it, so do not use it in this way.
326
327
\param s The r/w semaphore to count the readers on.
328
\return The number of readers holding the r/w semaphore.
329
*/
330
int
rwsem_read_count
(
rw_semaphore_t
*s);
331
332
/** \brief Read the state of the writer lock on the reader/writer semaphore.
333
334
This function is not a safe way to see if the lock will be locked by a
335
writer by the time you get around to doing something with it, so don't try
336
to use it for that purpose.
337
338
\param s The r/w semaphore to check the writer status on.
339
\return The status of the writer lock of the r/w semaphore.
340
*/
341
int
rwsem_write_locked
(
rw_semaphore_t
*s);
342
343
__END_DECLS
344
345
#endif
/* __KOS_RWSEM_H */
Generated by
1.8.1.1