KallistiOS  ##version##
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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 
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? */
45 
46  /** \brief The number of readers that are currently holding the lock. */
48 
49  /** \brief The thread holding the write lock. */
51 
52  /** \brief Space for one reader who's trying to upgrade to a writer. */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
342 
343 __END_DECLS
344 
345 #endif /* __KOS_RWSEM_H */
int initialized
Are we initialized?
Definition: rwsem.h:44
int rwsem_write_lock(rw_semaphore_t *s)
Lock a reader/writer semaphore for writing.
kthread_t * write_lock
The thread holding the write lock.
Definition: rwsem.h:50
int rwsem_read_lock_timed(rw_semaphore_t *s, int timeout)
Lock a reader/writer semaphore for reading (with a timeout).
int rwsem_write_unlock(rw_semaphore_t *s)
Unlock a reader/writer semaphore from a write lock.
int rwsem_unlock(rw_semaphore_t *s)
Unlock a reader/writer semaphore.
rw_semaphore_t * rwsem_create() __attribute__((deprecated))
Allocate a reader/writer semaphore.
int rwsem_read_upgrade(rw_semaphore_t *s)
Upgrade a thread from reader status to writer status.
int rwsem_read_upgrade_timed(rw_semaphore_t *s, int timeout)
Upgrade a thread from reader status to writer status (with a timeout).
int read_count
The number of readers that are currently holding the lock.
Definition: rwsem.h:47
int rwsem_read_unlock(rw_semaphore_t *s)
Unlock a reader/writer semaphore from a read lock.
Threading support.
int rwsem_write_lock_timed(rw_semaphore_t *s, int timeout)
Lock a reader/writer semaphore for writing (with a timeout).
struct rw_semaphore rw_semaphore_t
Reader/writer semaphore structure.
int rwsem_init(rw_semaphore_t *s)
Initialize 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_destroy(rw_semaphore_t *s)
Destroy a reader/writer semaphore.
int rwsem_read_lock(rw_semaphore_t *s)
Lock a reader/writer semaphore for reading.
int rwsem_write_trylock(rw_semaphore_t *s)
Attempt to lock a reader/writer semaphore for writing.
Reader/writer semaphore structure.
Definition: rwsem.h:42
Structure describing one running thread.
Definition: thread.h:90
int rwsem_read_count(rw_semaphore_t *s)
Read the reader count on the reader/writer semaphore.
int rwsem_write_locked(rw_semaphore_t *s)
Read the state of the writer lock on the reader/writer semaphore.
kthread_t * reader_waiting
Space for one reader who's trying to upgrade to a writer.
Definition: rwsem.h:53
int rwsem_read_trylock(rw_semaphore_t *s)
Attempt to lock a reader/writer semaphore for reading.