KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
sem.h
Go to the documentation of this file.
1/* KallistiOS ##version##
2
3 include/kos/sem.h
4 Copyright (C) 2001, 2003 Megan Potter
5 Copyright (C) 2012 Lawrence Sebald
6
7*/
8
9/** \file kos/sem.h
10 \brief Semaphores.
11 \ingroup kthreads
12
13 This file defines semaphores. A semaphore is a synchronization primitive
14 that allows a specified number of threads to be in its critical section at a
15 single point of time. Another way to think of it is that you have a
16 predetermined number of resources available, and the semaphore maintains the
17 resources.
18
19 \author Megan Potter
20 \see kos/mutex.h
21*/
22
23#ifndef __KOS_SEM_H
24#define __KOS_SEM_H
25
26#include <kos/cdefs.h>
27
28__BEGIN_DECLS
29
30/** \brief Semaphore type.
31
32 This structure defines a semaphore. There are no public members of this
33 structure for you to actually do anything with in your code, so don't try.
34
35 \headerfile kos/sem.h
36*/
37typedef struct semaphore {
38 int initialized; /**< \brief Are we initialized? */
39 int count; /**< \brief The semaphore count */
41
42/** \brief Initializer for a transient semaphore.
43 \param value The initial count of the semaphore. */
44#define SEM_INITIALIZER(value) { 1, value }
45
46/** \brief Initialize a semaphore for use.
47
48 This function initializes the semaphore passed in with the starting count
49 value specified.
50
51 \param sm The semaphore to initialize
52 \param count The initial count of the semaphore
53 \retval 0 On success
54 \retval -1 On error, errno will be set as appropriate
55
56 \par Error Conditions:
57 \em EINVAL - the semaphore's value is invalid (less than 0)
58*/
59int sem_init(semaphore_t *sm, int count);
60
61/** \brief Destroy a semaphore.
62
63 This function destroys a semaphore, leaving it uninitialized. If there
64 are any threads currently waiting on the semaphore, they will be woken
65 with an ENOTRECOVERABLE error.
66
67 \param sm The semaphore to destroy
68 \retval 0 On success (no error conditions currently defined)
69*/
70int sem_destroy(semaphore_t *sm) __nonnull_all;
71
72/** \brief Wait on a semaphore (with a timeout).
73
74 This function will decrement the semaphore's count and return, if resources
75 are available. Otherwise, the function will block until the resources become
76 available or the timeout expires.
77
78 This function does not protect you against doing things that will cause a
79 deadlock. This function is not safe to call in an interrupt. See
80 sem_trywait() for a safe function to call in an interrupt.
81
82 \param sm The semaphore to wait on
83 \param timeout The maximum number of milliseconds to block (a value
84 of 0 here will block indefinitely)
85 \retval 0 On success
86 \retval -1 On error, sets errno as appropriate
87
88 \par Error Conditions:
89 \em EPERM - called inside an interrupt \n
90 \em ETIMEDOUT - timed out while blocking
91 */
92int sem_wait_timed(semaphore_t *sm, unsigned int timeout) __nonnull_all;
93
94/** \brief Wait on a semaphore.
95
96 This function will decrement the semaphore's count and return, if resources
97 are available. Otherwise, the function will block until the resources become
98 available.
99
100 This function does not protect you against doing things that will cause a
101 deadlock. This function is not safe to call in an interrupt. See
102 sem_trywait() for a safe function to call in an interrupt.
103
104 \param sm The semaphore to wait on
105 \retval 0 On success
106 \retval -1 On error, sets errno as appropriate
107
108 \par Error Conditions: None defined
109*/
110__nonnull_all
111static inline int sem_wait(semaphore_t *sm) {
112 return sem_wait_timed(sm, 0);
113}
114
115/** \brief "Wait" on a semaphore without blocking.
116
117 This function will decrement the semaphore's count and return, if resources
118 are available. Otherwise, it will return an error.
119
120 This function does not protect you against doing things that will cause a
121 deadlock. This function, unlike the other waiting functions is safe to call
122 inside an interrupt.
123
124 \param sm The semaphore to "wait" on
125 \retval 0 On success
126 \retval -1 On error, sets errno as appropriate
127
128 \par Error Conditions:
129 \em EWOULDBLOCK - a call to sem_wait() would block \n
130*/
131int sem_trywait(semaphore_t *sm) __nonnull_all;
132
133/** \brief Wait on a semaphore.
134
135 This function will decrement the semaphore's count and return, if resources
136 are available. Otherwise, the function will block until the resources become
137 available.
138
139 This function can be used from within an interrupt context. In that case, if
140 the semaphore is already used, an error will be returned.
141
142 \param sm The semaphore to wait on
143 \retval 0 On success
144 \retval -1 On error, sets errno as appropriate
145
146 \par Error Conditions:
147 \em EWOULDBLOCK - the function was called inside an interrupt and the
148 semaphore is not free \n
149*/
150int sem_wait_irqsafe(semaphore_t *sm) __nonnull_all;
151
152/** \brief Signal a semaphore.
153
154 This function will release resources associated with a semaphore, signalling
155 a waiting thread to continue on, if any are waiting. It is your
156 responsibility to make sure you only release resources you have.
157
158 \param sm The semaphore to signal
159 \retval 0 On success
160 \retval -1 On error, sets errno as appropriate
161
162 \par Error Conditions: None defined
163*/
164int sem_signal(semaphore_t *sm) __nonnull_all;
165
166/** \brief Retrieve the number of available resources.
167
168 This function will retrieve the count of available resources for a
169 semaphore. This is not a thread-safe way to make sure resources will be
170 available when you get around to waiting, so don't use it as such.
171
172 \param sm The semaphore to check
173 \return The count of the semaphore (the number of resources
174 currently available)
175*/
176int sem_count(const semaphore_t *sm) __nonnull_all;
177
178/** \cond */
179static inline void __sem_scoped_cleanup(semaphore_t **sm) {
180 if(*sm)
181 sem_signal(*sm);
182}
183
184#define ___sem_wait_scoped(sm, l) \
185 semaphore_t *__scoped_sem_##l __attribute__((cleanup(__sem_scoped_cleanup))) = sem_wait(sm) ? NULL : (sm)
186
187#define __sem_wait_scoped(sm, l) ___sem_wait_scoped(sm, l)
188/** \endcond */
189
190/** \brief Wait on a semaphore with scope management
191
192 This macro will wait on a semaphore, similarly to sem_wait, with the
193 difference that the semaphore will automatically be signaled once the
194 execution exits the functional block in which the macro was called.
195
196 \param sm The semaphore to wait on
197*/
198#define sem_wait_scoped(sm) __sem_wait_scoped((sm), __LINE__)
199
200__END_DECLS
201
202#endif /* __KOS_SEM_H */
Various common macros used throughout the codebase.
static __nonnull_all int sem_wait(semaphore_t *sm)
Wait on a semaphore.
Definition sem.h:111
int sem_count(const semaphore_t *sm) __nonnull_all
Retrieve the number of available resources.
int sem_destroy(semaphore_t *sm) __nonnull_all
Destroy a semaphore.
int sem_wait_timed(semaphore_t *sm, unsigned int timeout) __nonnull_all
Wait on a semaphore (with a timeout).
int sem_init(semaphore_t *sm, int count)
Initialize a semaphore for use.
int sem_wait_irqsafe(semaphore_t *sm) __nonnull_all
Wait on a semaphore.
int sem_trywait(semaphore_t *sm) __nonnull_all
"Wait" on a semaphore without blocking.
int sem_signal(semaphore_t *sm) __nonnull_all
Signal a semaphore.
Semaphore type.
Definition sem.h:37
int initialized
Are we initialized?
Definition sem.h:38
int count
The semaphore count.
Definition sem.h:39