ChibiOS 21.11.5
chdelegates.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio.
3
4 This file is part of ChibiOS.
5
6 ChibiOS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 3 of the License.
9
10 ChibiOS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file oslib/src/chdelegates.c
21 * @brief Delegate threads code.
22 * @details Delegate threads.
23 * <h2>Operation mode</h2>
24 * A delegate thread is a thread performing function calls triggered
25 * by other threads. This functionality is especially useful when
26 * encapsulating a library not designed for threading into a
27 * delegate thread. Other threads have access to the library without
28 * having to worry about mutual exclusion.
29 * @pre In order to use the delegates APIs the @p CH_CFG_USE_DELEGATES
30 * option must be enabled in @p chconf.h.
31 * @note Compatible with RT and NIL.
32 *
33 * @addtogroup oslib_delegates
34 * @{
35 */
36
37#include "ch.h"
38
39#if (CH_CFG_USE_DELEGATES == TRUE) || defined(__DOXYGEN__)
40
41/*===========================================================================*/
42/* Module local definitions. */
43/*===========================================================================*/
44
45/*===========================================================================*/
46/* Module exported variables. */
47/*===========================================================================*/
48
49/*===========================================================================*/
50/* Module local types. */
51/*===========================================================================*/
52
53/**
54 * @brief Type of a structure representing a delegate call.
55 */
56typedef struct {
57 /**
58 * @brief The delegate veneer function.
59 */
60 delegate_veneer_t veneer;
61 /**
62 * @brief Pointer to the caller @p va_list object.
63 */
64 va_list *argsp;
65} call_message_t;
66
67/*===========================================================================*/
68/* Module local variables. */
69/*===========================================================================*/
70
71/*===========================================================================*/
72/* Module local functions. */
73/*===========================================================================*/
74
75/*===========================================================================*/
76/* Module exported functions. */
77/*===========================================================================*/
78
79/*lint -save -e586 [17.1] Required by design.*/
80
81/**
82 * @brief Veneer for functions with no parameters.
83 *
84 * @param[in] argsp the list of arguments
85 * @return The function return value.
86 */
87msg_t __ch_delegate_fn0(va_list *argsp) {
88 delegate_fn0_t fn0 = (delegate_fn0_t)va_arg(*argsp, delegate_fn0_t);
89 return fn0();
90}
91
92/**
93 * @brief Veneer for functions with one parameter.
94 *
95 * @param[in] argsp the list of arguments
96 * @return The function return value.
97 */
98msg_t __ch_delegate_fn1(va_list *argsp) {
99 delegate_fn1_t fn1 = (delegate_fn1_t)va_arg(*argsp, delegate_fn1_t);
100 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
101 return fn1(p1);
102}
103
104/**
105 * @brief Veneer for functions with two parameters.
106 *
107 * @param[in] argsp the list of arguments
108 * @return The function return value.
109 */
110msg_t __ch_delegate_fn2(va_list *argsp) {
111 delegate_fn2_t fn2 = (delegate_fn2_t)va_arg(*argsp, delegate_fn2_t);
112 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
113 msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
114 return fn2(p1, p2);
115}
116
117/**
118 * @brief Veneer for functions with three parameters.
119 *
120 * @param[in] argsp the list of arguments
121 * @return The function return value.
122 */
123msg_t __ch_delegate_fn3(va_list *argsp) {
124 delegate_fn3_t fn3 = (delegate_fn3_t)va_arg(*argsp, delegate_fn3_t);
125 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
126 msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
127 msg_t p3 = (msg_t)va_arg(*argsp, msg_t);
128 return fn3(p1, p2, p3);
129}
130
131/**
132 * @brief Veneer for functions with four parameters.
133 *
134 * @param[in] argsp the list of arguments
135 * @return The function return value.
136 */
137msg_t __ch_delegate_fn4(va_list *argsp) {
138 delegate_fn4_t fn4 = (delegate_fn4_t)va_arg(*argsp, delegate_fn4_t);
139 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
140 msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
141 msg_t p3 = (msg_t)va_arg(*argsp, msg_t);
142 msg_t p4 = (msg_t)va_arg(*argsp, msg_t);
143 return fn4(p1, p2, p3, p4);
144}
145
146/**
147 * @brief Triggers a function call on a delegate thread.
148 * @note The thread must be executing @p chDelegateDispatchTimeout() in
149 * order to have the functions called.
150 *
151 * @param[in] tp pointer to the delegate thread
152 * @param[in] veneer pointer to the veneer function to be called
153 * @param[in] ... variable number of parameters
154 * @return The function return value casted to msg_t. It is
155 * garbage for functions returning @p void.
156 */
158 va_list args;
159 call_message_t cm;
160 msg_t msg;
161
162 chDbgCheck((tp != NULL) && (veneer != NULL));
163
164 va_start(args, veneer);
165
166 /* Preparing the call message.*/
167 cm.veneer = veneer;
168 cm.argsp = &args;
169
170 /* Sending the message to the dispatcher thread, the return value is
171 contained in the returned message.*/
172 msg = chMsgSend(tp, (msg_t)&cm);
173
174 va_end(args);
175
176 return msg;
177}
178
179/*lint -restore*/
180
181/**
182 * @brief Call messages dispatching.
183 * @details The function awaits for an incoming call messages and calls the
184 * specified functions, then it returns. In case multiple threads
185 * are sending messages then the requests are served in priority
186 * order.
187 *
188 * @api
189 */
191 thread_t *tp;
192 const call_message_t *cmp;
193 msg_t ret;
194
195 tp = chMsgWait();
196 cmp = (const call_message_t *)chMsgGet(tp);
197 ret = cmp->veneer(cmp->argsp);
198
199 chMsgRelease(tp, ret);
200}
201
202/**
203 * @brief Call messages dispatching with timeout.
204 * @details The function awaits for an incoming call messages and calls the
205 * specified functions, then it returns. In case multiple threads
206 * are sending messages then the requests are served in priority
207 * order.
208 *
209 * @param[in] timeout the number of ticks before the operation timeouts,
210 * the following special values are allowed:
211 * - @a TIME_IMMEDIATE immediate timeout.
212 * - @a TIME_INFINITE no timeout.
213 * .
214 * @return The function outcome.
215 * @retval MSG_OK if a function has been called.
216 * @retval MSG_TIMEOUT if a timeout occurred.
217 *
218 * @api
219 */
221 thread_t *tp;
222 const call_message_t *cmp;
223 msg_t ret;
224
225 tp = chMsgWaitTimeout(timeout);
226 if (tp == NULL) {
227 return MSG_TIMEOUT;
228 }
229
230 cmp = (const call_message_t *)chMsgGet(tp);
231 ret = cmp->veneer(cmp->argsp);
232
233 chMsgRelease(tp, ret);
234
235 return MSG_OK;
236}
237
238#endif /* CH_CFG_USE_DELEGATES == TRUE */
239
240/** @} */
#define chMsgGet(tp)
Returns the message carried by the specified thread.
#define chDbgCheck(c)
Function parameters check.
Definition chdebug.h:117
static thread_t * chMsgWait(void)
Suspends the thread and waits for an incoming message.
msg_t chMsgSend(thread_t *tp, msg_t msg)
Sends a message to the specified thread.
void chMsgRelease(thread_t *tp, msg_t msg)
Releases a sender thread specifying a response message.
static thread_t * chMsgWaitTimeout(sysinterval_t timeout)
Suspends the thread and waits for an incoming message or a timeout to occur.
int32_t msg_t
Definition chearly.h:87
struct ch_thread thread_t
Type of a thread structure.
Definition chearly.h:132
msg_t __ch_delegate_fn3(va_list *argsp)
Veneer for functions with three parameters.
msg_t __ch_delegate_fn4(va_list *argsp)
Veneer for functions with four parameters.
msg_t(* delegate_fn4_t)(msg_t p1, msg_t p2, msg_t p3, msg_t p4)
Type of a delegate function with four parameters.
Definition chdelegates.h:84
msg_t(* delegate_fn1_t)(msg_t p1)
Type of a delegate function with one parameter.
Definition chdelegates.h:69
msg_t(* delegate_fn0_t)(void)
Type of a delegate function with no parameters.
Definition chdelegates.h:64
msg_t(* delegate_fn3_t)(msg_t p1, msg_t p2, msg_t p3)
Type of a delegate function with three parameters.
Definition chdelegates.h:79
msg_t chDelegateDispatchTimeout(sysinterval_t timeout)
Call messages dispatching with timeout.
msg_t __ch_delegate_fn0(va_list *argsp)
Veneer for functions with no parameters.
Definition chdelegates.c:87
msg_t chDelegateCallVeneer(thread_t *tp, delegate_veneer_t veneer,...)
Triggers a function call on a delegate thread.
msg_t(* delegate_fn2_t)(msg_t p1, msg_t p2)
Type of a delegate function with two parameters.
Definition chdelegates.h:74
msg_t __ch_delegate_fn2(va_list *argsp)
Veneer for functions with two parameters.
msg_t __ch_delegate_fn1(va_list *argsp)
Veneer for functions with one parameter.
Definition chdelegates.c:98
msg_t(* delegate_veneer_t)(va_list *argsp)
Type of a delegate veneer function.
Definition chdelegates.h:59
void chDelegateDispatch(void)
Call messages dispatching.
#define MSG_OK
Normal wakeup message.
Definition chschd.h:38
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition chschd.h:39
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:118