VSF Documented
vsf_eda_sync.c
Go to the documentation of this file.
1/*****************************************************************************
2 * Copyright(C)2009-2022 by VSF Team *
3 * *
4 * Licensed under the Apache License, Version 2.0 (the "License"); *
5 * you may not use this file except in compliance with the License. *
6 * You may obtain a copy of the License at *
7 * *
8 * http://www.apache.org/licenses/LICENSE-2.0 *
9 * *
10 * Unless required by applicable law or agreed to in writing, software *
11 * distributed under the License is distributed on an "AS IS" BASIS, *
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13 * See the License for the specific language governing permissions and *
14 * limitations under the License. *
15 * *
16 ****************************************************************************/
17
18
19/*============================ INCLUDES ======================================*/
20
22
23#if VSF_USE_KERNEL == ENABLED && defined(__EDA_GADGET__)
24
25/*============================ MACROS ========================================*/
26/*============================ MACROFIED FUNCTIONS ===========================*/
27/*============================ TYPES =========================================*/
28/*============================ GLOBAL VARIABLES ==============================*/
29/*============================ LOCAL VARIABLES ===============================*/
30/*============================ PROTOTYPES ====================================*/
31
32VSF_CAL_SECTION(".text.vsf.kernel.__vsf_teda_cancel_timer")
34
35/*============================ IMPLEMENTATION ================================*/
36
37
38#if VSF_KERNEL_CFG_SUPPORT_SYNC == ENABLED
39
40/*-----------------------------------------------------------------------------*
41 * vsf_sync_t for critical_section, semaphore, event *
42 *-----------------------------------------------------------------------------*/
43
44VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
45vsf_eda_t * __vsf_eda_sync_set_timeout(vsf_eda_t *eda, vsf_timeout_tick_t timeout)
46{
47 eda = __vsf_eda_get_valid_eda(eda);
48
49 if (timeout > 0) {
50#if VSF_KERNEL_CFG_EDA_SUPPORT_TIMER == ENABLED
51 eda->flag.state.is_limitted = true;
52# ifdef __VSF_OS_CFG_EVTQ_LIST
53 // If timeout is too close, VSF_EVT_TIMER will be issued before eda->is_ready cleared,
54 // __vsf_evtq_post(evtq_list) will ignore the VSF_EVT_TIMER event.
55 // So just record due and set is_to_set_due,
56 // timer will be set after eda->is_ready cleared in vsf_evtq_poll(evtq_list).
57 eda->flag.state.is_to_set_due = true;
58 ((vsf_teda_t *)eda)->due = vsf_systimer_get_tick() + timeout;
59# else
61# endif
62#else
63 #ifndef WEAK_VSF_KERNEL_ERR_REPORT
65 #else
66 WEAK_VSF_KERNEL_ERR_REPORT(VSF_KERNEL_ERR_EDA_DOES_NOT_SUPPORT_TIMER);
67 #endif
68#endif
69 }
70 return eda;
71}
72
73VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
75{
76 eda = __vsf_eda_get_valid_eda(eda);
77 VSF_KERNEL_ASSERT(eda != NULL);
78
80 vsf_eda_t, pending_node,
81 &sync->pending_list,
82 eda);
83
84 __vsf_eda_sync_set_timeout(eda, timeout);
85}
86
87VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
88static vsf_eda_t *__vsf_eda_sync_get_eda_pending(vsf_sync_t *sync)
89{
90 vsf_eda_t *eda;
91
93 vsf_eda_t, pending_node,
94 &sync->pending_list,
95 eda);
96 return eda;
97}
98
99#if __IS_COMPILER_LLVM__ || __IS_COMPILER_ARM_COMPILER_6__
100# pragma clang diagnostic push
101# pragma clang diagnostic ignored "-Wcast-align"
102#endif
103
104#if __IS_COMPILER_GCC__
105# pragma GCC diagnostic push
106# pragma GCC diagnostic ignored "-Wcast-align"
107#endif
108
109VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
110static vsf_sync_reason_t __vsf_eda_sync_get_reason( vsf_sync_t *sync,
111 vsf_evt_t evt,
112 bool dequeue_eda)
113{
114 vsf_eda_t *eda = vsf_eda_get_cur();
115 VSF_KERNEL_ASSERT(eda != NULL);
117
118 VSF_KERNEL_ASSERT((sync != NULL) && (eda != NULL));
119
120#if VSF_KERNEL_CFG_EDA_SUPPORT_TIMER == ENABLED
121 if (evt == VSF_EVT_TIMER) {
122 vsf_protect_t origlevel = vsf_protect_sched();
123 if (eda->flag.state.is_sync_got) {
124 vsf_unprotect_sched(origlevel);
125 return VSF_SYNC_PENDING;
126 }
127 if (dequeue_eda) {
129 vsf_eda_t, pending_node,
130 &sync->pending_list,
131 eda);
132 }
133 vsf_unprotect_sched(origlevel);
134 reason = VSF_SYNC_TIMEOUT;
135 } else {
137#else
138 {
139#endif
140 if (evt == VSF_EVT_SYNC) {
141 reason = VSF_SYNC_GET;
142 eda->flag.state.is_sync_got = false;
143 } else if (evt == VSF_EVT_SYNC_CANCEL) {
144 reason = VSF_SYNC_CANCEL;
145 eda->flag.state.is_sync_got = false;
146 } else {
147 VSF_KERNEL_ASSERT(false);
148 }
149 }
150 eda->flag.state.is_limitted = false;
151 return reason;
152}
153
154#if __IS_COMPILER_LLVM__ || __IS_COMPILER_ARM_COMPILER_6__
155# pragma clang diagnostic pop
156#endif
157#if __IS_COMPILER_GCC__
158# pragma GCC diagnostic pop
159#endif
160
161VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
163{
164 VSF_KERNEL_ASSERT(pthis != NULL);
165
166 pthis->cur_union.cur_value = cur;
167 pthis->max_union.max_value = max;
168 vsf_dlist_init(&pthis->pending_list);
169 if (pthis->cur_union.bits.has_owner) {
170 ((vsf_sync_owner_t *)pthis)->eda_owner = NULL;
171 }
172 return VSF_ERR_NONE;
173}
174
175#if VSF_SYNC_CFG_SUPPORT_ISR == ENABLED
176VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
178{
179 VSF_KERNEL_ASSERT(pthis != NULL);
180 return vsf_eda_post_msg((vsf_eda_t *)&__vsf_eda.task, pthis);
181}
182#endif // VSF_SYNC_CFG_SUPPORT_ISR
183
184VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
186{
187 vsf_protect_t origlevel;
188 vsf_eda_t *eda_pending;
189
190 VSF_KERNEL_ASSERT(pthis != NULL);
191
192 origlevel = vsf_protect_sched();
193 if (pthis->cur_union.bits.cur >= pthis->max_union.bits.max) {
194 vsf_unprotect_sched(origlevel);
195 return VSF_ERR_OVERRUN;
196 }
197 pthis->cur_union.bits.cur++;
198#if VSF_KERNEL_CFG_SUPPORT_DYNAMIC_PRIOTIRY == ENABLED
199 if (pthis->cur_union.bits.has_owner) {
200 eda = __vsf_eda_get_valid_eda(eda);
201// although not good to remove the assertion below,
202// but some applications use mutex as sem or trigger, and will assert here
203// VSF_KERNEL_ASSERT(((vsf_sync_owner_t *)pthis)->eda_owner == eda);
204 ((vsf_sync_owner_t *)pthis)->eda_owner = NULL;
205 if (eda->cur_priority != eda->priority) {
206 __vsf_eda_set_priority(eda, (vsf_prio_t)eda->priority);
207 } else if (eda->flag.state.is_new_prio) {
208 vsf_evtq_t *evtq;
209 // assert new_priority is a priority boost
210 VSF_KERNEL_ASSERT(eda->new_priority > eda->priority);
211 eda->flag.state.is_new_prio = false;
212
213 evtq = __vsf_os_evtq_get((vsf_prio_t)eda->priority);
214 VSF_KERNEL_ASSERT(evtq != NULL);
215 __vsf_os_evtq_set_priority(evtq, eda->priority);
216 }
217 }
218#endif
219
220 while (1) {
221 if (pthis->cur_union.bits.cur > 0) {
222 eda_pending = __vsf_eda_sync_get_eda_pending(pthis);
223 if (eda_pending != NULL) {
224 eda_pending->flag.state.is_sync_got = true;
225 if (!manual) {
226 pthis->cur_union.bits.cur--;
227 }
228#if VSF_KERNEL_CFG_SUPPORT_DYNAMIC_PRIOTIRY == ENABLED
229 if (pthis->cur_union.bits.has_owner) {
230 ((vsf_sync_owner_t *)pthis)->eda_owner = eda_pending;
231 }
232#endif
233 }
234 vsf_unprotect_sched(origlevel);
235
236 if (eda_pending != NULL) {
237 vsf_err_t err = __vsf_eda_post_evt_ex(eda_pending, VSF_EVT_SYNC, true);
238 VSF_KERNEL_ASSERT(!err);
239 VSF_UNUSED_PARAM(err);
240 origlevel = vsf_protect_sched();
241 continue;
242 } else {
243 break;
244 }
245 } else {
246 vsf_unprotect_sched(origlevel);
247 break;
248 }
249 }
250 return VSF_ERR_NONE;
251}
252
253VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
255{
256 return __vsf_eda_sync_increase_ex(pthis, eda, pthis->max_union.bits.manual_rst);
257}
258
259VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
261{
262 return vsf_eda_sync_increase_ex(pthis, NULL);
263}
264
265VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
267{
268 vsf_protect_t origlevel = vsf_protect_sched();
269 pthis->cur_union.bits.cur = 0;
270 vsf_unprotect_sched(origlevel);
271}
272
273VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
275{
276 vsf_protect_t origlevel;
277
278 VSF_KERNEL_ASSERT(pthis != NULL);
279
280 eda = __vsf_eda_get_valid_eda(eda);
281
282 origlevel = vsf_protect_sched();
283 if ((pthis->cur_union.bits.cur > 0) && vsf_dlist_is_empty(&pthis->pending_list)) {
284 if (!manual) {
285 pthis->cur_union.bits.cur--;
286 }
287#if VSF_KERNEL_CFG_SUPPORT_DYNAMIC_PRIOTIRY == ENABLED
288 if (pthis->cur_union.bits.has_owner) {
289 VSF_KERNEL_ASSERT((NULL == ((vsf_sync_owner_t *)pthis)->eda_owner) && (0 == pthis->cur_union.bits.cur));
290 ((vsf_sync_owner_t *)pthis)->eda_owner = eda;
291 }
292#endif
293 vsf_unprotect_sched(origlevel);
294 return VSF_ERR_NONE;
295 }
296
297 if (timeout != 0) {
298#if VSF_KERNEL_CFG_SUPPORT_DYNAMIC_PRIOTIRY == ENABLED
299 if (pthis->cur_union.bits.has_owner) {
301 vsf_prio_t cur_priority = __vsf_eda_get_cur_priority(eda);
303 vsf_eda_t, pending_node,
304 &pthis->pending_list,
305 eda,
306 _->cur_priority < cur_priority);
307 __vsf_eda_sync_set_timeout(eda, timeout);
308 } else
309#endif
310 {
311 __vsf_eda_sync_pend(pthis, eda, timeout);
312 }
313#if VSF_KERNEL_CFG_SUPPORT_DYNAMIC_PRIOTIRY == ENABLED
314 if (pthis->cur_union.bits.has_owner) {
315 vsf_eda_t *eda_owner = ((vsf_sync_owner_t *)pthis)->eda_owner;
316
317 if (eda->cur_priority > eda_owner->cur_priority) {
318 __vsf_eda_set_priority(eda_owner, (vsf_prio_t)eda->cur_priority);
319 }
320 }
321#endif
322 }
323 vsf_unprotect_sched(origlevel);
324 return VSF_ERR_NOT_READY;
325}
326
327VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
329{
330 return __vsf_eda_sync_decrease_ex(pthis, timeout, eda, pthis->max_union.bits.manual_rst);
331}
332
333VSF_CAL_SECTION(".text.vsf.kernel.vsf_sync")
335{
336 return vsf_eda_sync_decrease_ex(pthis, timeout, NULL);
337}
338
339VSF_CAL_SECTION(".text.vsf.kernel.vsf_eda_sync_cancel")
341{
342 vsf_eda_t *eda;
343 vsf_protect_t origlevel;
344
345 VSF_KERNEL_ASSERT(pthis != NULL);
346
347 do {
348 origlevel = vsf_protect_sched();
349 eda = __vsf_eda_sync_get_eda_pending(pthis);
350 if (eda != NULL) {
351 eda->flag.state.is_sync_got = true;
352 vsf_unprotect_sched(origlevel);
354 } else {
355 vsf_unprotect_sched(origlevel);
356 }
357 } while (eda != NULL);
358}
359
360VSF_CAL_SECTION(".text.vsf.kernel.vsf_eda_sync_get_reason")
362{
363 return __vsf_eda_sync_get_reason(pthis, evt, true);
364}
365
366
367#endif
368
369
370#endif
#define VSF_CAL_SECTION(__SEC_STR)
Definition __compiler.h:189
#define VSF_UNUSED_PARAM(__VAL)
Definition __type.h:190
vsf_err_t
Definition __type.h:42
@ VSF_ERR_NONE
none error
Definition __type.h:44
@ VSF_ERR_NOT_READY
service not ready yet
Definition __type.h:43
@ VSF_ERR_OVERRUN
overrun
Definition __type.h:60
The event-driven task (TCB); every VSF task is an eda at the bottom. Tasks share stacks and only occu...
Definition vsf_eda.h:1838
Sync object with an owner (mutex base); supports priority inheritance; the owner must leave it itself...
Definition vsf_eda.h:2009
Base sync IPC object; sem/mutex/trig/crit are built on it.
Definition vsf_eda.h:1964
eda with timer support (can use vsf_teda_set_timer() etc.); derived classes (task/pt/thread) inherit ...
Definition vsf_eda.h:1916
__le16 timeout
Definition ieee80211.h:94
#define NULL
Definition lvgl.h:26
#define max(x, y)
Definition minmax.h:12
unsigned short uint_fast16_t
Definition stdint.h:25
Definition vsf_evtq.h:51
void sync(void)
Definition vsf_linux_fs.c:2284
uintalu_t vsf_protect_t
Definition vsf_arch_abstraction.h:60
vsf_eda_t * vsf_eda_get_cur(void)
Get the eda task currently being dispatched.
Definition vsf_eda.c:416
vsf_err_t __vsf_os_evtq_set_priority(vsf_evtq_t *pthis, vsf_prio_t priority)
Definition vsf_os.c:345
vsf_err_t vsf_eda_post_msg(vsf_eda_t *pthis, void *msg)
Post a pointer message to an eda task; the task receives VSF_EVT_MESSAGE and retrieves the pointer wi...
Definition vsf_eda.c:961
vsf_err_t __vsf_eda_post_evt_ex(vsf_eda_t *pthis, vsf_evt_t evt, bool force)
Definition vsf_eda.c:953
void vsf_kernel_err_report(enum vsf_kernel_error_t err)
Report a kernel error.
Definition vsf_eda.c:409
int16_t vsf_evt_t
Kernel event type.
Definition vsf_eda.h:1658
vsf_err_t vsf_eda_sync_init(vsf_sync_t *pthis, uint_fast16_t cur_value, uint_fast16_t max_value)
Initialize a sync object, the base of semaphore, mutex, trigger etc.
vsf_sync_reason_t vsf_eda_sync_get_reason(vsf_sync_t *pthis, vsf_evt_t evt)
Retrieve the result of a sync operation from the wakeup event.
vsf_err_t vsf_eda_sync_increase(vsf_sync_t *pthis)
Increase a sync object, waking up the pending tasks if any.
@ VSF_KERNEL_ERR_EDA_DOES_NOT_SUPPORT_TIMER
Timer service used on an eda without timer support.
Definition vsf_eda.h:2375
vsf_err_t vsf_eda_sync_decrease(vsf_sync_t *pthis, vsf_timeout_tick_t timeout)
Decrease a sync object, pending if the resource is not available.
vsf_systimer_tick_t vsf_systimer_get_tick(void)
Get the current system timer tick count.
VSF_KERNEL_TIMEOUT_TICK_T vsf_timeout_tick_t
Timeout type in system timer ticks: negative means wait forever, 0 means non-blocking try,...
Definition vsf_eda.h:1491
vsf_err_t vsf_teda_set_timer_ex(vsf_teda_t *pthis, vsf_systimer_tick_t tick)
Set a one-shot timer of the given ticks for the given teda task; the task receives VSF_EVT_TIMER when...
vsf_err_t __vsf_eda_sync_decrease_ex(vsf_sync_t *pthis, vsf_timeout_tick_t timeout, vsf_eda_t *eda, bool manual)
Decrease a sync object with an explicit manual-reset flag.
@ VSF_EVT_SYNC_CANCEL
The pending sync IPC was cancelled (e.g. by vsf_eda_sync_cancel())
Definition vsf_eda.h:1583
@ VSF_EVT_SYNC
A pending sync IPC (semaphore/mutex/trigger/queue/bmpevt) was obtained.
Definition vsf_eda.h:1577
@ VSF_EVT_TIMER
teda timer expired (only for teda tasks)
Definition vsf_eda.h:1569
void vsf_eda_sync_force_reset(vsf_sync_t *pthis)
Force the count of a sync object to 0.
vsf_err_t __vsf_eda_sync_increase_ex(vsf_sync_t *pthis, vsf_eda_t *eda, bool manual)
Increase a sync object with an explicit manual-reset flag.
vsf_err_t vsf_eda_sync_increase_isr(vsf_sync_t *pthis)
Increase a sync object from interrupt context.
vsf_err_t vsf_eda_sync_decrease_ex(vsf_sync_t *pthis, vsf_timeout_tick_t timeout, vsf_eda_t *eda)
Decrease a sync object on behalf of the given eda.
vsf_err_t __vsf_teda_cancel_timer(vsf_teda_t *pthis)
Cancel the pending timer of the given teda task.
vsf_sync_reason_t
Result of a sync wait, returned by the *_get_reason() APIs and thread IPC.
Definition vsf_eda.h:2262
@ VSF_SYNC_GET
Obtained.
Definition vsf_eda.h:2282
@ VSF_SYNC_FAIL
Failed/error.
Definition vsf_eda.h:2267
@ VSF_SYNC_CANCEL
Cancelled.
Definition vsf_eda.h:2287
@ VSF_SYNC_TIMEOUT
Timed out.
Definition vsf_eda.h:2272
@ VSF_SYNC_PENDING
Still waiting, retry.
Definition vsf_eda.h:2277
vsf_err_t vsf_eda_sync_increase_ex(vsf_sync_t *pthis, vsf_eda_t *eda)
Increase a sync object on behalf of the given eda (e.g. the owner of a mutex)
void vsf_eda_sync_cancel(vsf_sync_t *pthis)
Cancel all pending tasks on a sync object; they are woken with VSF_EVT_SYNC_CANCEL.
vsf_prio_t __vsf_eda_get_cur_priority(vsf_eda_t *pthis)
Definition vsf_evtq_list.c:77
vsf_err_t __vsf_eda_set_priority(vsf_eda_t *pthis, vsf_prio_t priority)
Definition vsf_evtq_list.c:84
#define VSF_KERNEL_ASSERT
Definition vsf_kernel_cfg.h:32
vsf_prio_t
Kernel priority enumeration.
Definition vsf_kernel_common.h:55
void __vsf_eda_sync_pend(vsf_sync_t *sync, vsf_eda_t *eda, vsf_timeout_tick_t timeout)
#define vsf_dlist_insert( __host_type, __member, __list_ptr, __item_ptr, __cond)
Definition vsf_list.h:769
#define vsf_dlist_queue_dequeue(__host_type, __member, __list_ptr, __item_ref_ptr)
Definition vsf_list.h:859
#define vsf_dlist_remove( __host_type, __member, __list_ptr, __item_ptr)
Definition vsf_list.h:810
#define vsf_dlist_is_empty(__list_ptr)
Definition vsf_list.h:705
#define vsf_dlist_init(__list_ptr)
Definition vsf_list.h:702
#define vsf_dlist_queue_enqueue(__host_type, __member, __list_ptr, __item_ptr)
Definition vsf_list.h:852
struct @908::@920 _
#define vsf_protect_sched()
Lock the scheduler and return the previous status as vsf_protect_t.
Definition vsf_os.h:271
#define vsf_unprotect_sched(__prot)
Restore the scheduler lock status saved by vsf_protect_sched()
Definition vsf_os.h:283
vsf_evtq_t * __vsf_os_evtq_get(vsf_prio_t priority)
Definition vsf_os.c:328
Generated from commit: vsfteam/vsf@c46986d