ChibiOS  21.6.0
nil/src/chsem.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
3  2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
4 
5  This file is part of ChibiOS.
6 
7  ChibiOS is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation version 3 of the License.
10 
11  ChibiOS is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /**
21  * @file nil/src/chsem.c
22  * @brief Nil RTOS semaphores source file.
23  *
24  * @addtogroup NIL_SEMAPHORES
25  * @{
26  */
27 
28 #include "ch.h"
29 
30 #if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
31 
32 /*===========================================================================*/
33 /* Module local definitions. */
34 /*===========================================================================*/
35 
36 /*===========================================================================*/
37 /* Module exported variables. */
38 /*===========================================================================*/
39 
40 /*===========================================================================*/
41 /* Module local variables. */
42 /*===========================================================================*/
43 
44 /*===========================================================================*/
45 /* Module local functions. */
46 /*===========================================================================*/
47 
48 /*===========================================================================*/
49 /* Module interrupt handlers. */
50 /*===========================================================================*/
51 
52 /*===========================================================================*/
53 /* Module exported functions. */
54 /*===========================================================================*/
55 
56 /**
57  * @brief Performs a wait operation on a semaphore with timeout specification.
58  *
59  * @param[in] sp pointer to a @p semaphore_t structure
60  * @param[in] timeout the number of ticks before the operation timeouts,
61  * the following special values are allowed:
62  * - @a TIME_IMMEDIATE immediate timeout.
63  * - @a TIME_INFINITE no timeout.
64  * .
65  * @return A message specifying how the invoking thread has been
66  * released from the semaphore.
67  * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
68  * semaphore has been signaled.
69  * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
70  * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
71  * the specified timeout.
72  *
73  * @api
74  */
76  msg_t msg;
77 
78  chSysLock();
79  msg = chSemWaitTimeoutS(sp, timeout);
80  chSysUnlock();
81 
82  return msg;
83 }
84 
85 /**
86  * @brief Performs a wait operation on a semaphore with timeout specification.
87  *
88  * @param[in] sp pointer to a @p semaphore_t structure
89  * @param[in] timeout the number of ticks before the operation timeouts,
90  * the following special values are allowed:
91  * - @a TIME_IMMEDIATE immediate timeout.
92  * - @a TIME_INFINITE no timeout.
93  * .
94  * @return A message specifying how the invoking thread has been
95  * released from the semaphore.
96  * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
97  * semaphore has been signaled.
98  * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
99  * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
100  * the specified timeout.
101  *
102  * @sclass
103  */
105 
106  chDbgCheckClassS();
107  chDbgCheck(sp != NULL);
108 
109  /* Note, the semaphore counter is a volatile variable so accesses are
110  manually optimized.*/
111  cnt_t cnt = sp->cnt;
112  if (cnt <= (cnt_t)0) {
113  if (TIME_IMMEDIATE == timeout) {
114 
115  return MSG_TIMEOUT;
116  }
117  sp->cnt = cnt - (cnt_t)1;
118  nil.current->u1.semp = sp;
119 
120  return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
121  }
122  sp->cnt = cnt - (cnt_t)1;
123 
124  return MSG_OK;
125 }
126 
127 /**
128  * @brief Performs a signal operation on a semaphore.
129  *
130  * @param[in] sp pointer to a @p semaphore_t structure
131  *
132  * @api
133  */
135 
136  chSysLock();
137  chSemSignalI(sp);
139  chSysUnlock();
140 }
141 
142 /**
143  * @brief Performs a signal operation on a semaphore.
144  * @post This function does not reschedule so a call to a rescheduling
145  * function must be performed before unlocking the kernel. Note that
146  * interrupt handlers always reschedule on exit so an explicit
147  * reschedule must not be performed in ISRs.
148  *
149  * @param[in] sp pointer to a @p semaphore_t structure
150  *
151  * @iclass
152  */
154 
155  chDbgCheckClassI();
156  chDbgCheck(sp != NULL);
157 
158  if (++sp->cnt <= (cnt_t)0) {
159  thread_t *tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)sp);
160 
161  chDbgAssert(tp != NULL, "thread not found");
162 
163  (void) chSchReadyI(tp, MSG_OK);
164  }
165 }
166 
167 /**
168  * @brief Performs a reset operation on the semaphore.
169  * @post After invoking this function all the threads waiting on the
170  * semaphore, if any, are released and the semaphore counter is set
171  * to the specified, non negative, value.
172  * @post This function does not reschedule so a call to a rescheduling
173  * function must be performed before unlocking the kernel. Note that
174  * interrupt handlers always reschedule on exit so an explicit
175  * reschedule must not be performed in ISRs.
176  *
177  * @param[in] sp pointer to a @p semaphore_t structure
178  * @param[in] n the new value of the semaphore counter. The value must
179  * be non-negative.
180  * @param[in] msg message to be sent
181  *
182  * @api
183  */
185 
186  chSysLock();
187  chSemResetWithMessageI(sp, n, msg);
189  chSysUnlock();
190 }
191 
192 /**
193  * @brief Performs a reset operation on the semaphore.
194  * @post After invoking this function all the threads waiting on the
195  * semaphore, if any, are released and the semaphore counter is set
196  * to the specified, non negative, value.
197  * @post This function does not reschedule so a call to a rescheduling
198  * function must be performed before unlocking the kernel. Note that
199  * interrupt handlers always reschedule on exit so an explicit
200  * reschedule must not be performed in ISRs.
201  *
202  * @param[in] sp pointer to a @p semaphore_t structure
203  * @param[in] n the new value of the semaphore counter. The value must
204  * be non-negative.
205  * @param[in] msg message to be sent
206  *
207  * @iclass
208  */
210  cnt_t cnt;
211 
212  chDbgCheckClassI();
213  chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
214 
215  cnt = sp->cnt;
216  sp->cnt = n;
217 
218  /* Does nothing for cnt >= 0, calling anyway.*/
219  (void) nil_ready_all((void *)sp, cnt, msg);
220 }
221 
222 #endif /* CH_CFG_USE_SEMAPHORES == TRUE */
223 
224 /** @} */
chSchReadyI
thread_t * chSchReadyI(thread_t *tp)
Inserts a thread in the Ready List placing it behind its peers.
Definition: chschd.c:276
chDbgAssert
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:144
NIL_STATE_WTQUEUE
#define NIL_STATE_WTQUEUE
On queue or semaph.
Definition: nil/include/ch.h:146
nil_ready_all
cnt_t nil_ready_all(void *p, cnt_t cnt, msg_t msg)
Puts in ready state all thread matching the specified status and associated object.
Definition: ch.c:95
msg_t
int32_t msg_t
Definition: chearly.h:88
chSchGoSleepTimeoutS
msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout)
Puts the current thread to sleep into the specified state with timeout specification.
Definition: chschd.c:355
chDbgCheck
#define chDbgCheck(c)
Function parameters check.
Definition: chdebug.h:118
TIME_IMMEDIATE
#define TIME_IMMEDIATE
Zero interval specification for some functions with a timeout specification.
Definition: chtime.h:47
nil
os_instance_t nil
System data structures.
Definition: ch.c:41
ch_thread
Structure representing a thread.
Definition: chobjects.h:156
chSemWaitTimeoutS
msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout)
Performs a wait operation on a semaphore with timeout specification.
Definition: nil/src/chsem.c:104
cnt_t
int32_t cnt_t
Definition: chearly.h:92
ch_semaphore
Semaphore structure.
Definition: rt/include/chsem.h:52
chSemSignalI
void chSemSignalI(semaphore_t *sp)
Performs a signal operation on a semaphore.
Definition: nil/src/chsem.c:153
chSchRescheduleS
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition: chschd.c:454
chSemResetWithMessage
void chSemResetWithMessage(semaphore_t *sp, cnt_t n, msg_t msg)
Performs a reset operation on the semaphore.
Definition: nil/src/chsem.c:184
MSG_OK
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
ch_semaphore::cnt
cnt_t cnt
The semaphore counter.
Definition: rt/include/chsem.h:55
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
MSG_TIMEOUT
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition: chschd.h:40
nil_find_thread
thread_t * nil_find_thread(tstate_t state, void *p)
Retrieves the highest priority thread in the specified state and associated to the specified object.
Definition: ch.c:70
chSemResetWithMessageI
void chSemResetWithMessageI(semaphore_t *sp, cnt_t n, msg_t msg)
Performs a reset operation on the semaphore.
Definition: nil/src/chsem.c:209
chSemWaitTimeout
msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout)
Performs a wait operation on a semaphore with timeout specification.
Definition: nil/src/chsem.c:75
chSemSignal
void chSemSignal(semaphore_t *sp)
Performs a signal operation on a semaphore.
Definition: nil/src/chsem.c:134
chSysUnlock
#define chSysUnlock()
Leaves the kernel lock state.
Definition: nil/include/ch.h:1053
chSysLock
#define chSysLock()
Enters the kernel lock state.
Definition: nil/include/ch.h:1043