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 The number of readers that are currently holding the lock. */
46
47 /** \brief The thread holding the write lock. */
49
50 /** \brief Space for one reader who's trying to upgrade to a writer. */
53
54/** \brief Initializer for a transient reader/writer semaphore */
55#define RWSEM_INITIALIZER { 0, NULL, NULL }
56
57/** \brief Initialize a reader/writer semaphore.
58
59 This function initializes a new reader/writer semaphore for use.
60
61 \retval 0 On success (no error conditions currently defined).
62*/
63int rwsem_init(rw_semaphore_t *s) __nonnull_all;
64
65/** \brief Destroy a reader/writer semaphore.
66
67 This function cleans up a reader/writer semaphore. It is an error to attempt
68 to destroy a r/w semaphore that is locked either for reading or writing.
69
70 \param s The r/w semaphore to destroy.
71 \retval 0 On success.
72 \retval -1 On error, errno will be set as appropriate.
73
74 \par Error Conditions:
75 \em EBUSY - the semaphore is still locked
76*/
77int rwsem_destroy(rw_semaphore_t *s) __nonnull_all;
78
79/** \brief Lock a reader/writer semaphore for reading (with a timeout).
80
81 This function attempts to lock the r/w semaphore for reading. If the
82 semaphore is locked for writing, this function will block until it is
83 possible to obtain the lock for reading or the timeout expires. This
84 function is <b>NOT</b> safe to call inside of an interrupt.
85
86 \param s The r/w semaphore to lock.
87 \param timeout The maximum time to wait (in milliseconds).
88 \retval 0 On success
89 \retval -1 On error, errno will be set as appropriate.
90
91 \par Error Conditions:
92 \em EPERM - called inside an interrupt \n
93 \em ETIMEDOUT - the timeout expires before the lock can be acquired \n
94 \em EINVAL - the timeout value is invalid \n
95 \em EINVAL - the semaphore is not initialized
96*/
97int rwsem_read_lock_timed(rw_semaphore_t *s, int timeout) __nonnull_all;
98
99/** \brief Lock a reader/writer semaphore for reading.
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. This function is <b>NOT</b> safe to
104 call inside of an interrupt; use rwsem_read_lock_irqsafe instead.
105
106 \param s The r/w semaphore to lock.
107 \retval 0 On success
108 \retval -1 On error, errno will be set as appropriate.
109
110 \par Error Conditions:
111 \em EPERM - called inside an interrupt \n
112 \em EINVAL - the semaphore is not initialized
113*/
114int rwsem_read_lock(rw_semaphore_t *s) __nonnull_all;
115
116/** \brief Lock a reader/writer semaphore for reading.
117
118 This function attempts to lock the r/w semaphore for reading. If the
119 semaphore is locked for writing, this function will block until it is
120 possible to obtain the lock for reading.
121 If called within an interrupt context, and the semaphore is already locked,
122 this function will return an error.
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 EINVAL - the semaphore is not initialized \n
130 \em EWOULDBLOCK - called inside an interrupt and the semaphore was
131 already locked
132*/
134
135/** \brief Lock a reader/writer semaphore for writing (with a timeout).
136
137 This function attempts to lock the r/w semaphore for writing. If the
138 semaphore is locked for reading or writing, this function will block until
139 it is possible to obtain the lock for writing or the timeout expires. This
140 function is <b>NOT</b> safe to call inside of an interrupt.
141
142 \param s The r/w semaphore to lock.
143 \param timeout The maximum time to wait (in milliseconds).
144 \retval 0 On success.
145 \retval -1 On error, errno will be set as appropriate.
146
147 \par Error Conditions:
148 \em EPERM - called inside an interrupt \n
149 \em ETIMEDOUT - the timeout expires before the lock can be acquired \n
150 \em EINVAL - the timeout value is invalid \n
151 \em EINVAL - the semaphore is not initialized
152*/
153int rwsem_write_lock_timed(rw_semaphore_t *s, int timeout) __nonnull_all;
154
155/** \brief Lock a reader/writer semaphore for writing.
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. This function is <b>NOT</b>
160 safe to call inside of an interrupt; use rwsem_write_lock_irqsafe instead.
161
162 \param s The r/w semaphore to lock.
163 \retval 0 On success.
164 \retval -1 On error, errno will be set as appropriate.
165
166 \par Error conditions:
167 \em EPERM - called inside an interrupt \n
168 \em EINVAL - the semaphore is not initialized
169*/
170int rwsem_write_lock(rw_semaphore_t *s) __nonnull_all;
171
172/** \brief Lock a reader/writer semaphore for writing.
173
174 This function attempts to lock the r/w semaphore for writing. If the
175 semaphore is locked for reading or writing, this function will block until
176 it is possible to obtain the lock for writing.
177 If called within an interrupt context, and the semaphore is already locked,
178 this function will return an error.
179
180 \param s The r/w semaphore to lock.
181 \retval 0 On success.
182 \retval -1 On error, errno will be set as appropriate.
183
184 \par Error conditions:
185 \em EINVAL - the semaphore is not initialized \n
186 \em EWOULDBLOCK - called inside an interrupt and the semaphore was
187 already locked
188*/
190
191/** \brief Unlock a reader/writer semaphore from a read lock.
192
193 This function releases one instance of the read lock on the r/w semaphore.
194
195 \param s The r/w semaphore to release the read lock on.
196 \retval 0 On success.
197 \retval -1 On error, errno will be set as appropriate.
198
199 \par Error Conditions:
200 \em EPERM - the read lock is not currently held \n
201 \em EINVAL - the semaphore is not initialized
202*/
203int rwsem_read_unlock(rw_semaphore_t *s) __nonnull_all;
204
205/** \brief Unlock a reader/writer semaphore from a write lock.
206
207 This function releases one instance of the write lock on the r/w semaphore.
208
209 \param s The r/w semaphore to release the write 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 write lock is not currently held by the calling
215 thread \n
216 \em EINVAL - the semaphore is not initialized
217*/
218int rwsem_write_unlock(rw_semaphore_t *s) __nonnull_all;
219
220/** \brief Unlock a reader/writer semaphore.
221
222 This function releases the lock held by the current thread on the specified
223 reader/writer semaphore. This function will automatically determine which
224 lock is held by the calling thread and release it as appropriate.
225
226 This function is <b>NOT</b> safe to call (in general) if you do not hold the
227 lock!
228
229 \param s The r/w semaphore to release the 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 lock is not currently held by the calling thread \n
235 \em EINVAL - the semaphore is not initialized
236*/
237int rwsem_unlock(rw_semaphore_t *s) __nonnull_all;
238
239/** \brief Attempt to lock a reader/writer semaphore for reading.
240
241 This function attempts to lock the r/w semaphore for reading. If for any
242 reason rwsem_read_lock would normally block, this function will return an
243 error. This function is safe to call inside an interrupt.
244
245 \param s The r/w semaphore to attempt to lock.
246 \retval 0 On success.
247 \retval -1 On error, errno will be set as appropriate.
248
249 \par Error Conditions:
250 \em EWOULDBLOCK - a call to rwsem_read_lock would block \n
251 \em EINVAL - the semaphore is not initialized
252*/
253int rwsem_read_trylock(rw_semaphore_t *s) __nonnull_all;
254
255/** \brief Attempt to lock a reader/writer semaphore for writing.
256
257 This function attempts to lock the r/w semaphore for writing. If for any
258 reason rwsem_write_lock would normally block, this function will return an
259 error. This function is safe to call inside an interrupt.
260
261 \param s The r/w semaphore to attempt to lock.
262 \retval 0 On success.
263 \retval -1 On error, errno will be set as appropriate.
264
265 \par Error Conditions:
266 \em EWOULDBLOCK - a call to rwsem_write_lock would block \n
267 \em EINVAL - the semaphore is not initialized
268*/
270
271/** \brief Upgrade a thread from reader status to writer status (with a
272 timeout).
273
274 This function will upgrade the lock on the calling thread from a reader
275 state to a writer state. If it cannot do this at the moment, it will block
276 until it is possible. This function is <b>NOT</b> safe to call inside an
277 interrupt.
278
279 You can only have one reader waiting to upgrade at a time, otherwise the
280 state would potentially become corrupted between when this is called and
281 when you get the lock. If you get -1 back from this, you must not assume
282 that you can write safely! On error, the calling thread will still hold a
283 read lock.
284
285 \param s The r/w semaphore to upgrade.
286 \param timeout The maximum time to wait (in milliseconds).
287 \retval 0 On success.
288 \retval -1 On error, errno will be set as appropriate.
289
290 \par Error Conditions:
291 \em EPERM - called inside an interrupt \n
292 \em EINVAL - the semaphore is not initialized \n
293 \em EINVAL - the timeout value is invalid \n
294 \em EBUSY - another reader has already requested an upgrade \n
295 \em ETIMEDOUT - the timeout expired before the write lock could be
296 acquired
297*/
298int rwsem_read_upgrade_timed(rw_semaphore_t *s, int timeout) __nonnull_all;
299
300/** \brief Upgrade a thread from reader status to writer status.
301
302 This function will upgrade the lock on the calling thread from a reader
303 state to a writer state. If it cannot do this at the moment, it will block
304 until it is possible. This function is <b>NOT</b> safe to call inside an
305 interrupt.
306
307 You can only have one reader waiting to upgrade at a time, otherwise the
308 state would potentially become corrupted between when this is called and
309 when you get the lock. If you get -1 back from this, you must not assume
310 that you can write safely! On error, the calling thread will still hold a
311 read lock.
312
313 \param s The r/w semaphore to upgrade.
314 \retval 0 On success.
315 \retval -1 On error, errno will be set as appropriate.
316
317 \par Error Conditions:
318 \em EPERM - called inside an interrupt \n
319 \em EINVAL - the semaphore is not initialized \n
320 \em EBUSY - another reader has already requested an upgrade
321*/
322int rwsem_read_upgrade(rw_semaphore_t *s) __nonnull_all;
323
324/** \brief Attempt to upgrade a thread from reader status to writer status.
325
326 This function will attempt to upgrade the lock on the calling thread to
327 writer status. If for any reason rwsem_read_upgrade would block, this
328 function will return an error. This function is safe to call inside an
329 interrupt. Note that on error, the read lock is still held!
330
331 \param s The r/w semaphore to upgrade.
332 \retval 0 On success.
333 \retval -1 On error, errno will be set as appropriate.
334
335 \par Error Conditions:
336 \em EWOULDBLOCK - a call to rwsem_read_upgrade would block \n
337 \em EBUSY - another reader has already requested an upgrade \n
338 \em EINVAL - the semaphore is not initialized
339*/
341
342/** \brief Read the reader count on the reader/writer semaphore.
343
344 This function is not a safe way to see if the lock will be locked by any
345 readers when you get around to locking it, so do not use it in this way.
346
347 \param s The r/w semaphore to count the readers on.
348 \return The number of readers holding the r/w semaphore.
349*/
350int rwsem_read_count(const rw_semaphore_t *s) __nonnull_all;
351
352/** \brief Read the state of the writer lock on the reader/writer semaphore.
353
354 This function is not a safe way to see if the lock will be locked by a
355 writer by the time you get around to doing something with it, so don't try
356 to use it for that purpose.
357
358 \param s The r/w semaphore to check the writer status on.
359 \return The status of the writer lock of the r/w semaphore.
360*/
361int rwsem_write_locked(const rw_semaphore_t *s) __nonnull_all;
362
363__END_DECLS
364
365#endif /* __KOS_RWSEM_H */
Various common macros used throughout the codebase.
int rwsem_write_unlock(rw_semaphore_t *s) __nonnull_all
Unlock a reader/writer semaphore from a write lock.
int rwsem_read_trylock(rw_semaphore_t *s) __nonnull_all
Attempt to lock a reader/writer semaphore for reading.
int rwsem_write_lock(rw_semaphore_t *s) __nonnull_all
Lock a reader/writer semaphore for writing.
int rwsem_unlock(rw_semaphore_t *s) __nonnull_all
Unlock a reader/writer semaphore.
int rwsem_write_trylock(rw_semaphore_t *s) __nonnull_all
Attempt to lock a reader/writer semaphore for writing.
int rwsem_read_tryupgrade(rw_semaphore_t *s) __nonnull_all
Attempt to upgrade a thread from reader status to writer status.
int rwsem_read_lock_timed(rw_semaphore_t *s, int timeout) __nonnull_all
Lock a reader/writer semaphore for reading (with a timeout).
int rwsem_read_upgrade_timed(rw_semaphore_t *s, int timeout) __nonnull_all
Upgrade a thread from reader status to writer status (with a timeout).
int rwsem_write_lock_irqsafe(rw_semaphore_t *s) __nonnull_all
Lock a reader/writer semaphore for writing.
int rwsem_read_unlock(rw_semaphore_t *s) __nonnull_all
Unlock a reader/writer semaphore from a read lock.
int rwsem_read_count(const rw_semaphore_t *s) __nonnull_all
Read the reader count on the reader/writer semaphore.
int rwsem_read_lock(rw_semaphore_t *s) __nonnull_all
Lock a reader/writer semaphore for reading.
int rwsem_read_lock_irqsafe(rw_semaphore_t *s) __nonnull_all
Lock a reader/writer semaphore for reading.
int rwsem_read_upgrade(rw_semaphore_t *s) __nonnull_all
Upgrade a thread from reader status to writer status.
int rwsem_write_locked(const rw_semaphore_t *s) __nonnull_all
Read the state of the writer lock on the reader/writer semaphore.
int rwsem_write_lock_timed(rw_semaphore_t *s, int timeout) __nonnull_all
Lock a reader/writer semaphore for writing (with a timeout).
int rwsem_init(rw_semaphore_t *s) __nonnull_all
Initialize a reader/writer semaphore.
int rwsem_destroy(rw_semaphore_t *s) __nonnull_all
Destroy a reader/writer semaphore.
Structure describing one running thread.
Definition thread.h:164
Reader/writer semaphore structure.
Definition rwsem.h:43
int read_count
The number of readers that are currently holding the lock.
Definition rwsem.h:45
kthread_t * write_lock
The thread holding the write lock.
Definition rwsem.h:48
kthread_t * reader_waiting
Space for one reader who's trying to upgrade to a writer.
Definition rwsem.h:51
Threading support.