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