ChibiOS  21.6.0
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  */
57 typedef 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  */
88 msg_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  */
99 msg_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  */
111 msg_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  */
124 msg_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  */
138 msg_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  */
190 void chDelegateDispatch(void) {
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 /** @} */
chMsgGet
#define chMsgGet(tp)
Returns the message carried by the specified thread.
Definition: nil/include/chmsg.h:85
chDelegateDispatch
void chDelegateDispatch(void)
Call messages dispatching.
Definition: chdelegates.c:190
__ch_delegate_fn0
msg_t __ch_delegate_fn0(va_list *argsp)
Veneer for functions with no parameters.
Definition: chdelegates.c:88
msg_t
int32_t msg_t
Definition: chearly.h:88
__ch_delegate_fn4
msg_t __ch_delegate_fn4(va_list *argsp)
Veneer for functions with four parameters.
Definition: chdelegates.c:138
delegate_fn3_t
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
__ch_delegate_fn1
msg_t __ch_delegate_fn1(va_list *argsp)
Veneer for functions with one parameter.
Definition: chdelegates.c:99
chMsgWait
thread_t * chMsgWait(void)
Suspends the thread and waits for an incoming message.
Definition: nil/src/chmsg.c:100
delegate_fn4_t
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
chDelegateDispatchTimeout
msg_t chDelegateDispatchTimeout(sysinterval_t timeout)
Call messages dispatching with timeout.
Definition: chdelegates.c:219
ch_thread
Structure representing a thread.
Definition: chobjects.h:156
__ch_delegate_fn2
msg_t __ch_delegate_fn2(va_list *argsp)
Veneer for functions with two parameters.
Definition: chdelegates.c:111
chMsgSend
msg_t chMsgSend(thread_t *tp, msg_t msg)
Sends a message to the specified thread.
Definition: rt/src/chmsg.c:81
delegate_fn0_t
msg_t(* delegate_fn0_t)(void)
Type of a delegate function with no parameters.
Definition: chdelegates.h:65
delegate_fn2_t
msg_t(* delegate_fn2_t)(msg_t p1, msg_t p2)
Type of a delegate function with two parameters.
Definition: chdelegates.h:75
chDelegateCallVeneer
msg_t chDelegateCallVeneer(thread_t *tp, delegate_veneer_t veneer,...)
Triggers a function call on a delegate thread.
Definition: chdelegates.c:158
MSG_OK
#define MSG_OK
Normal wakeup message.
Definition: chschd.h:39
chMsgRelease
void chMsgRelease(thread_t *tp, msg_t msg)
Releases a sender thread specifying a response message.
Definition: rt/src/chmsg.c:208
sysinterval_t
uint64_t sysinterval_t
Type of time interval.
Definition: chtime.h:119
delegate_veneer_t
msg_t(* delegate_veneer_t)(va_list *argsp)
Type of a delegate veneer function.
Definition: chdelegates.h:60
MSG_TIMEOUT
#define MSG_TIMEOUT
Wakeup caused by a timeout condition.
Definition: chschd.h:40
delegate_fn1_t
msg_t(* delegate_fn1_t)(msg_t p1)
Type of a delegate function with one parameter.
Definition: chdelegates.h:70
__ch_delegate_fn3
msg_t __ch_delegate_fn3(va_list *argsp)
Veneer for functions with three parameters.
Definition: chdelegates.c:124
chMsgWaitTimeout
thread_t * chMsgWaitTimeout(sysinterval_t timeout)
Suspends the thread and waits for an incoming message or a timeout to occur.
Definition: nil/src/chmsg.c:133