ChibiOS 21.11.4
chdelegates.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 oslib/src/chdelegates.c
22 * @brief Delegate threads code.
23 * @details Delegate threads.
24 * <h2>Operation mode</h2>
25 * A delegate thread is a thread performing function calls triggered
26 * by other threads. This functionality is especially useful when
27 * encapsulating a library not designed for threading into a
28 * delegate thread. Other threads have access to the library without
29 * having to worry about mutual exclusion.
30 * @pre In order to use the pipes APIs the @p CH_CFG_USE_DELEGATES
31 * option must be enabled in @p chconf.h.
32 * @note Compatible with RT and NIL.
33 *
34 * @addtogroup oslib_delegates
35 * @{
36 */
37
38#include "ch.h"
39
40#if (CH_CFG_USE_DELEGATES == TRUE) || defined(__DOXYGEN__)
41
42/*===========================================================================*/
43/* Module local definitions. */
44/*===========================================================================*/
45
46/*===========================================================================*/
47/* Module exported variables. */
48/*===========================================================================*/
49
50/*===========================================================================*/
51/* Module local types. */
52/*===========================================================================*/
53
54/**
55 * @brief Type of a structure representing a delegate call.
56 */
57typedef struct {
58 /**
59 * @brief The delegate veneer function.
60 */
61 delegate_veneer_t veneer;
62 /**
63 * @brief Pointer to the caller @p va_list object.
64 */
65 va_list *argsp;
66} call_message_t;
67
68/*===========================================================================*/
69/* Module local variables. */
70/*===========================================================================*/
71
72/*===========================================================================*/
73/* Module local functions. */
74/*===========================================================================*/
75
76/*===========================================================================*/
77/* Module exported functions. */
78/*===========================================================================*/
79
80/*lint -save -e586 [17.1] Required by design.*/
81
82/**
83 * @brief Veneer for functions with no parameters.
84 *
85 * @param[in] argsp the list of arguments
86 * @return The function return value.
87 */
88msg_t __ch_delegate_fn0(va_list *argsp) {
89 delegate_fn0_t fn0 = (delegate_fn0_t)va_arg(*argsp, delegate_fn0_t);
90 return fn0();
91}
92
93/**
94 * @brief Veneer for functions with one parameter.
95 *
96 * @param[in] argsp the list of arguments
97 * @return The function return value.
98 */
99msg_t __ch_delegate_fn1(va_list *argsp) {
100 delegate_fn1_t fn1 = (delegate_fn1_t)va_arg(*argsp, delegate_fn1_t);
101 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
102 return fn1(p1);
103}
104
105/**
106 * @brief Veneer for functions with two parameters.
107 *
108 * @param[in] argsp the list of arguments
109 * @return The function return value.
110 */
111msg_t __ch_delegate_fn2(va_list *argsp) {
112 delegate_fn2_t fn2 = (delegate_fn2_t)va_arg(*argsp, delegate_fn2_t);
113 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
114 msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
115 return fn2(p1, p2);
116}
117
118/**
119 * @brief Veneer for functions with three parameters.
120 *
121 * @param[in] argsp the list of arguments
122 * @return The function return value.
123 */
124msg_t __ch_delegate_fn3(va_list *argsp) {
125 delegate_fn3_t fn3 = (delegate_fn3_t)va_arg(*argsp, delegate_fn3_t);
126 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
127 msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
128 msg_t p3 = (msg_t)va_arg(*argsp, msg_t);
129 return fn3(p1, p2, p3);
130}
131
132/**
133 * @brief Veneer for functions with four parameters.
134 *
135 * @param[in] argsp the list of arguments
136 * @return The function return value.
137 */
138msg_t __ch_delegate_fn4(va_list *argsp) {
139 delegate_fn4_t fn4 = (delegate_fn4_t)va_arg(*argsp, delegate_fn4_t);
140 msg_t p1 = (msg_t)va_arg(*argsp, msg_t);
141 msg_t p2 = (msg_t)va_arg(*argsp, msg_t);
142 msg_t p3 = (msg_t)va_arg(*argsp, msg_t);
143 msg_t p4 = (msg_t)va_arg(*argsp, msg_t);
144 return fn4(p1, p2, p3, p4);
145}
146
147/**
148 * @brief Triggers a function call on a delegate thread.
149 * @note The thread must be executing @p chDelegateDispatchTimeout() in
150 * order to have the functions called.
151 *
152 * @param[in] tp pointer to the delegate thread
153 * @param[in] veneer pointer to the veneer function to be called
154 * @param[in] ... variable number of parameters
155 * @return The function return value casted to msg_t. It is
156 * garbage for functions returning @p void.
157 */
159 va_list args;
160 call_message_t cm;
161 msg_t msg;
162
163 va_start(args, veneer);
164
165 /* Preparing the call message.*/
166 cm.veneer = veneer;
167 cm.argsp = &args;
168 (void)cm; /* Suppresses a lint warning.*/
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_INFINITE no timeout.
212 * .
213 * @return The function outcome.
214 * @retval MSG_OK if a function has been called.
215 * @retval MSG_TIMEOUT if a timeout occurred.
216 *
217 * @api
218 */
220 thread_t *tp;
221 const call_message_t *cmp;
222 msg_t ret;
223
224 tp = chMsgWaitTimeout(timeout);
225 if (tp == NULL) {
226 return MSG_TIMEOUT;
227 }
228
229 cmp = (const call_message_t *)chMsgGet(tp);
230 ret = cmp->veneer(cmp->argsp);
231
232 chMsgRelease(tp, ret);
233
234 return MSG_OK;
235}
236
237#endif /* CH_CFG_USE_DELEGATES == TRUE */
238
239/** @} */
#define chMsgGet(tp)
Returns the message carried by the specified thread.
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:88
struct ch_thread thread_t
Type of a thread structure.
Definition chearly.h:133
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:85
msg_t(* delegate_fn1_t)(msg_t p1)
Type of a delegate function with one parameter.
Definition chdelegates.h:70
msg_t(* delegate_fn0_t)(void)
Type of a delegate function with no parameters.
Definition chdelegates.h:65
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:80
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:88
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:75
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:99
msg_t(* delegate_veneer_t)(va_list *argsp)
Type of a delegate veneer function.
Definition chdelegates.h:60
void chDelegateDispatch(void)
Call messages dispatching.
#define MSG_OK
Normal wakeup message.
Definition chschd.h:39
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition chschd.h:40
uint64_t sysinterval_t
Type of time interval.
Definition chtime.h:119