TNeo  v1.08
tn_sem.h
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * TNeo: real-time kernel initially based on TNKernel
4  *
5  * TNKernel: copyright 2004, 2013 Yuri Tiomkin.
6  * PIC32-specific routines: copyright 2013, 2014 Anders Montonen.
7  * TNeo: copyright 2014 Dmitry Frank.
8  *
9  * TNeo was born as a thorough review and re-implementation of
10  * TNKernel. The new kernel has well-formed code, inherited bugs are fixed
11  * as well as new features being added, and it is tested carefully with
12  * unit-tests.
13  *
14  * API is changed somewhat, so it's not 100% compatible with TNKernel,
15  * hence the new name: TNeo.
16  *
17  * Permission to use, copy, modify, and distribute this software in source
18  * and binary forms and its documentation for any purpose and without fee
19  * is hereby granted, provided that the above copyright notice appear
20  * in all copies and that both that copyright notice and this permission
21  * notice appear in supporting documentation.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  ******************************************************************************/
36 
37 /**
38  * \file
39  *
40  * A semaphore: an object to provide signaling mechanism.
41  *
42  * There is a lot of confusion about differences between semaphores and
43  * mutexes, so, it's quite recommended to read small article by Michael Barr:
44  * [Mutexes and Semaphores Demystified](http://goo.gl/YprPBW).
45  *
46  * Very short:
47  *
48  * While mutex is seemingly similar to a semaphore with maximum count of `1`
49  * (the so-called binary semaphore), their usage is very different: the purpose
50  * of mutex is to protect shared resource. A locked mutex is "owned" by the
51  * task that locked it, and only the same task may unlock it. This ownership
52  * allows to implement algorithms to prevent priority inversion. So, mutex is
53  * a *locking mechanism*.
54  *
55  * Semaphore, on the other hand, is *signaling mechanism*. It's quite legal and
56  * encouraged for semaphore to be waited for in the task A, and then signaled
57  * from task B or even from ISR. It may be used in situations like "producer
58  * and consumer", etc.
59  *
60  * In addition to the article mentioned above, you may want to look at the
61  * [related question on stackoverflow.com](http://goo.gl/ZBReHK).
62  *
63  */
64 
65 #ifndef _TN_SEM_H
66 #define _TN_SEM_H
67 
68 /*******************************************************************************
69  * INCLUDED FILES
70  ******************************************************************************/
71 
72 #include "tn_list.h"
73 #include "tn_common.h"
74 
75 
76 
77 #ifdef __cplusplus
78 extern "C" { /*}*/
79 #endif
80 
81 /*******************************************************************************
82  * PUBLIC TYPES
83  ******************************************************************************/
84 
85 /**
86  * Semaphore
87  */
88 struct TN_Sem {
89  ///
90  /// id for object validity verification.
91  /// This field is in the beginning of the structure to make it easier
92  /// to detect memory corruption.
94  ///
95  /// List of tasks that wait for the semaphore
97  ///
98  /// Current semaphore counter value
99  int count;
100  ///
101  /// Max value of `count`
103 };
104 
105 
106 /*******************************************************************************
107  * PROTECTED GLOBAL DATA
108  ******************************************************************************/
109 
110 /*******************************************************************************
111  * DEFINITIONS
112  ******************************************************************************/
113 
114 /*******************************************************************************
115  * PUBLIC FUNCTION PROTOTYPES
116  ******************************************************************************/
117 
118 /**
119  * Construct the semaphore. `id_sem` field should not contain
120  * `#TN_ID_SEMAPHORE`, otherwise, `#TN_RC_WPARAM` is returned.
121  *
122  * $(TN_CALL_FROM_TASK)
123  * $(TN_CALL_FROM_ISR)
124  * $(TN_LEGEND_LINK)
125  *
126  * @param sem
127  * Pointer to already allocated `struct TN_Sem`
128  * @param start_count
129  * Initial counter value, typically it is equal to `max_count`
130  * @param max_count
131  * Maximum counter value.
132  *
133  * @return
134  * * `#TN_RC_OK` if semaphore was successfully created;
135  * * If `#TN_CHECK_PARAM` is non-zero, additional return code
136  * is available: `#TN_RC_WPARAM`.
137  */
139  struct TN_Sem *sem,
140  int start_count,
141  int max_count
142  );
143 
144 /**
145  * Destruct the semaphore.
146  *
147  * All tasks that wait for the semaphore become runnable with
148  * `#TN_RC_DELETED` code returned.
149  *
150  * $(TN_CALL_FROM_TASK)
151  * $(TN_CAN_SWITCH_CONTEXT)
152  * $(TN_LEGEND_LINK)
153  *
154  * @param sem semaphore to destruct
155  *
156  * @return
157  * * `#TN_RC_OK` if semaphore was successfully deleted;
158  * * `#TN_RC_WCONTEXT` if called from wrong context;
159  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
160  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
161  */
162 enum TN_RCode tn_sem_delete(struct TN_Sem *sem);
163 
164 /**
165  * Signal the semaphore.
166  *
167  * If current semaphore counter (`count`) is less than `max_count`, counter is
168  * incremented by one, and first task (if any) that \ref tn_sem_wait() "waits"
169  * for the semaphore becomes runnable with `#TN_RC_OK` returned from
170  * `tn_sem_wait()`.
171  *
172  * if semaphore counter is already has its max value, no action performed and
173  * `#TN_RC_OVERFLOW` is returned
174  *
175  * $(TN_CALL_FROM_TASK)
176  * $(TN_CAN_SWITCH_CONTEXT)
177  * $(TN_LEGEND_LINK)
178  *
179  * @param sem semaphore to signal
180  *
181  * @return
182  * * `#TN_RC_OK` if successful
183  * * `#TN_RC_WCONTEXT` if called from wrong context;
184  * * `#TN_RC_OVERFLOW` if `count` is already at maximum value (`max_count`)
185  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
186  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
187  */
188 enum TN_RCode tn_sem_signal(struct TN_Sem *sem);
189 
190 /**
191  * The same as `tn_sem_signal()` but for using in the ISR.
192  *
193  * $(TN_CALL_FROM_ISR)
194  * $(TN_CAN_SWITCH_CONTEXT)
195  * $(TN_LEGEND_LINK)
196  *
197  */
198 enum TN_RCode tn_sem_isignal(struct TN_Sem *sem);
199 
200 /**
201  * Wait for the semaphore.
202  *
203  * If the current semaphore counter (`count`) is non-zero, it is decremented
204  * and `#TN_RC_OK` is returned. Otherwise, behavior depends on `timeout` value:
205  * task might switch to $(TN_TASK_STATE_WAIT) state until someone \ref
206  * tn_sem_signal "signaled" the semaphore or until the `timeout` expired. refer
207  * to `#TN_TickCnt`.
208  *
209  * $(TN_CALL_FROM_TASK)
210  * $(TN_CAN_SWITCH_CONTEXT)
211  * $(TN_CAN_SLEEP)
212  * $(TN_LEGEND_LINK)
213  *
214  * @param sem semaphore to wait for
215  * @param timeout refer to `#TN_TickCnt`
216  *
217  * @return
218  * * `#TN_RC_OK` if waiting was successfull
219  * * Other possible return codes depend on `timeout` value,
220  * refer to `#TN_TickCnt`
221  * * If `#TN_CHECK_PARAM` is non-zero, additional return codes
222  * are available: `#TN_RC_WPARAM` and `#TN_RC_INVALID_OBJ`.
223  */
224 enum TN_RCode tn_sem_wait(struct TN_Sem *sem, TN_TickCnt timeout);
225 
226 /**
227  * The same as `tn_sem_wait()` with zero timeout.
228  *
229  * $(TN_CALL_FROM_TASK)
230  * $(TN_CAN_SWITCH_CONTEXT)
231  * $(TN_LEGEND_LINK)
232  */
233 enum TN_RCode tn_sem_wait_polling(struct TN_Sem *sem);
234 
235 /**
236  * The same as `tn_sem_wait()` with zero timeout, but for using in the ISR.
237  *
238  * $(TN_CALL_FROM_ISR)
239  * $(TN_CAN_SWITCH_CONTEXT)
240  * $(TN_LEGEND_LINK)
241  */
242 enum TN_RCode tn_sem_iwait_polling(struct TN_Sem *sem);
243 
244 
245 #ifdef __cplusplus
246 } /* extern "C" */
247 #endif
248 
249 #endif // _TN_SEM_H
250 
251 /*******************************************************************************
252  * end of file
253  ******************************************************************************/
254 
255 
Semaphore.
Definition: tn_sem.h:88
Circular doubly linked list, for internal kernel usage.
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:81
TN_ObjId
Magic number for object validity verification.
Definition: tn_common.h:65
unsigned long TN_TickCnt
Type for system tick count, it is used by the kernel to represent absolute tick count value as well a...
Definition: tn_common.h:188
enum TN_RCode tn_sem_signal(struct TN_Sem *sem)
Signal the semaphore.
Definitions used through the whole kernel.
enum TN_RCode tn_sem_wait_polling(struct TN_Sem *sem)
The same as tn_sem_wait() with zero timeout.
struct TN_ListItem wait_queue
List of tasks that wait for the semaphore.
Definition: tn_sem.h:96
enum TN_ObjId id_sem
id for object validity verification.
Definition: tn_sem.h:93
enum TN_RCode tn_sem_iwait_polling(struct TN_Sem *sem)
The same as tn_sem_wait() with zero timeout, but for using in the ISR.
enum TN_RCode tn_sem_delete(struct TN_Sem *sem)
Destruct the semaphore.
enum TN_RCode tn_sem_isignal(struct TN_Sem *sem)
The same as tn_sem_signal() but for using in the ISR.
enum TN_RCode tn_sem_create(struct TN_Sem *sem, int start_count, int max_count)
Construct the semaphore.
int count
Current semaphore counter value.
Definition: tn_sem.h:99
enum TN_RCode tn_sem_wait(struct TN_Sem *sem, TN_TickCnt timeout)
Wait for the semaphore.
Circular doubly linked list item, for internal kernel usage.
Definition: tn_list.h:63
int max_count
Max value of count
Definition: tn_sem.h:102