µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
os-evflags.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2016-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#if defined(OS_USE_OS_APP_CONFIG_H)
13#include <cmsis-plus/os-app-config.h>
14#endif
15
16#include <cmsis-plus/rtos/os.h>
17
18// ----------------------------------------------------------------------------
19
20#if defined(__clang__)
21#pragma clang diagnostic ignored "-Wc++98-compat"
22#endif
23
24// ----------------------------------------------------------------------------
25
26namespace os
27{
28 namespace rtos
29 {
30 // ------------------------------------------------------------------------
31
52 const event_flags::attributes event_flags::initializer;
53
54 // ------------------------------------------------------------------------
55
129 : event_flags{ nullptr, attr }
130 {
131 }
132
133#pragma GCC diagnostic push
134#if defined(__clang__)
135#elif defined(__GNUC__)
136#pragma GCC diagnostic ignored "-Wunused-parameter"
137#endif
138
163 event_flags::event_flags (const char* name, const attributes& attr)
164 : object_named_system{ name }
165 {
166#if defined(OS_TRACE_RTOS_EVFLAGS)
167 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
168#endif
169
170 // Don't call this from interrupt handlers.
172
173#if !defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
174 clock_ = attr.clock != nullptr ? attr.clock : &sysclock;
175#endif
176
177#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
178
179 port::event_flags::create (this);
180
181#else
182
183#endif
184 }
185
186#pragma GCC diagnostic pop
187
202 {
203#if defined(OS_TRACE_RTOS_EVFLAGS)
204 trace::printf ("%s() @%p %s\n", __func__, this, name ());
205#endif
206
207#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
208
209 port::event_flags::destroy (this);
210
211#else
212
213 // There must be no threads waiting for these flags.
214 assert (list_.empty ());
215
216#endif
217 }
218
242 flags::mode_t mode)
243 {
244#if defined(OS_TRACE_RTOS_EVFLAGS)
245 trace::printf ("%s(0x%X,%u) @%p %s <0x%X\n", __func__, mask, mode, this,
246 name (), event_flags_.mask ());
247#endif
248
249 // Don't call this from interrupt handlers.
251 // Don't call this from critical regions.
253
254#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
255
256 return port::event_flags::wait (this, mask, oflags, mode);
257
258#else
259
260 {
261 // ----- Enter critical section ---------------------------------------
263
264 if (event_flags_.check_raised (mask, oflags, mode))
265 {
266#if defined(OS_TRACE_RTOS_EVFLAGS)
267 trace::printf ("%s(0x%X,%u) @%p %s >0x%X\n", __func__, mask, mode,
268 this, name (), event_flags_.mask ());
269#endif
270 return result::ok;
271 }
272 // ----- Exit critical section ----------------------------------------
273 }
274
275 thread& crt_thread = this_thread::thread ();
276
277 // Prepare a list node pointing to the current thread.
278 // Do not worry for being on stack, it is temporarily linked to the
279 // list and guaranteed to be removed before this function returns.
280 internal::waiting_thread_node node{ crt_thread };
281
282 for (;;)
283 {
284 {
285 // ----- Enter critical section -----------------------------------
287
288 if (event_flags_.check_raised (mask, oflags, mode))
289 {
290#if defined(OS_TRACE_RTOS_EVFLAGS)
291 trace::printf ("%s(0x%X,%u) @%p %s >0x%X\n", __func__, mask,
292 mode, this, name (), event_flags_.mask ());
293#endif
294 return result::ok;
295 }
296
297 // Add this thread to the event flags waiting list.
298 scheduler::internal_link_node (list_, node);
299 // state::suspended set in above link().
300 // ----- Exit critical section ------------------------------------
301 }
302
304
305 {
306 // ----- Enter critical section -----------------------------------
308
309 // Remove the thread from the event flags waiting list,
310 // if not already removed by raise().
311 scheduler::internal_unlink_node (node);
312 // ----- Exit critical section ------------------------------------
313 }
314
315 if (crt_thread.interrupted ())
316 {
317#if defined(OS_TRACE_RTOS_EVFLAGS)
318 trace::printf ("%s(0x%X,%u) EINTR @%p %s\n", __func__, mask,
319 mode, this, name ());
320#endif
321 return EINTR;
322 }
323 }
324
325 /* NOTREACHED */
326 return ENOTRECOVERABLE;
327
328#endif
329 }
330
344 flags::mode_t mode)
345 {
346#if defined(OS_TRACE_RTOS_EVFLAGS)
347 trace::printf ("%s(0x%X,%u) @%p %s <0x%X\n", __func__, mask, mode, this,
348 name (), event_flags_.mask ());
349#endif
350
351#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
352
353 return port::event_flags::try_wait (this, mask, oflags, mode);
354
355#else
356
357 // Don't call this from high priority interrupts.
358 assert (port::interrupts::is_priority_valid ());
359
360 {
361 // ----- Enter critical section ---------------------------------------
363
364 if (event_flags_.check_raised (mask, oflags, mode))
365 {
366#if defined(OS_TRACE_RTOS_EVFLAGS)
367 trace::printf ("%s(0x%X,%u) @%p %s >0x%X\n", __func__, mask, mode,
368 this, name (), event_flags_.mask ());
369#endif
370 return result::ok;
371 }
372 else
373 {
374#if defined(OS_TRACE_RTOS_EVFLAGS)
375 trace::printf ("%s(0x%X,%u) EWOULDBLOCK @%p %s \n", __func__, mask,
376 mode, this, name ());
377#endif
378 return EWOULDBLOCK;
379 }
380 // ----- Exit critical section ----------------------------------------
381 }
382
383#endif
384 }
385
426 flags::mask_t* oflags, flags::mode_t mode)
427 {
428#if defined(OS_TRACE_RTOS_EVFLAGS)
429 trace::printf ("%s(0x%X,%u,%u) @%p %s <0x%X\n", __func__, mask, timeout,
430 mode, this, name (), event_flags_.mask ());
431#endif
432
433 // Don't call this from interrupt handlers.
435 // Don't call this from critical regions.
437
438#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
439
440 return port::event_flags::timed_wait (this, mask, timeout, oflags, mode);
441
442#else
443
444 // Extra test before entering the loop, with its inherent weight.
445 // Trade size for speed.
446 {
447 // ----- Enter critical section ---------------------------------------
449
450 if (event_flags_.check_raised (mask, oflags, mode))
451 {
452#if defined(OS_TRACE_RTOS_EVFLAGS)
453 trace::printf ("%s(0x%X,%u,%u) @%p %s >0x%X\n", __func__, mask,
454 timeout, mode, this, name (), event_flags_.mask ());
455#endif
456 return result::ok;
457 }
458 // ----- Exit critical section ----------------------------------------
459 }
460
461 thread& crt_thread = this_thread::thread ();
462
463 // Prepare a list node pointing to the current thread.
464 // Do not worry for being on stack, it is temporarily linked to the
465 // list and guaranteed to be removed before this function returns.
466 internal::waiting_thread_node node{ crt_thread };
467
468 internal::clock_timestamps_list& clock_list = clock_->steady_list ();
469 clock::timestamp_t timeout_timestamp = clock_->steady_now () + timeout;
470
471 // Prepare a timeout node pointing to the current thread.
472 internal::timeout_thread_node timeout_node{ timeout_timestamp,
473 crt_thread };
474
475 for (;;)
476 {
477 {
478 // ----- Enter critical section -----------------------------------
480
481 if (event_flags_.check_raised (mask, oflags, mode))
482 {
483#if defined(OS_TRACE_RTOS_EVFLAGS)
484 trace::printf ("%s(0x%X,%u,%u) @%p %s >0x%X\n", __func__, mask,
485 timeout, mode, this, name (),
486 event_flags_.mask ());
487#endif
488 return result::ok;
489 }
490
491 // Add this thread to the event flags waiting list,
492 // and the clock timeout list.
493 scheduler::internal_link_node (list_, node, clock_list,
494 timeout_node);
495 // state::suspended set in above link().
496 // ----- Exit critical section ------------------------------------
497 }
498
500
501 // Remove the thread from the event flags waiting list,
502 // if not already removed by raise() and from the clock
503 // timeout list, if not already removed by the timer.
504 scheduler::internal_unlink_node (node, timeout_node);
505
506 if (crt_thread.interrupted ())
507 {
508#if defined(OS_TRACE_RTOS_EVFLAGS)
509 trace::printf ("%s(0x%X,%u,%u) EINTR @%p %s 0x%X \n", __func__,
510 mask, timeout, mode, this, name ());
511#endif
512 return EINTR;
513 }
514
515 if (clock_->steady_now () >= timeout_timestamp)
516 {
517#if defined(OS_TRACE_RTOS_EVFLAGS)
518 trace::printf ("%s(0x%X,%u,%u) ETIMEDOUT @%p %s 0x%X \n",
519 __func__, mask, timeout, mode, this, name ());
520#endif
521 return ETIMEDOUT;
522 }
523 }
524
525 /* NOTREACHED */
526 return ENOTRECOVERABLE;
527
528#endif
529 }
530
541 {
542#if defined(OS_TRACE_RTOS_EVFLAGS)
543 trace::printf ("%s(0x%X) @%p %s <0x%X \n", __func__, mask, this, name (),
544 event_flags_.mask ());
545#endif
546
547#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
548
549 os_assert_err (mask != 0, EINVAL);
550
551 return port::event_flags::raise (this, mask, oflags);
552
553#else
554
555 result_t res = event_flags_.raise (mask, oflags);
556
557 // Wake-up all threads, if any.
558 // Need not be inside the critical section,
559 // the list is protected by inner `resume_one()`.
560 list_.resume_all ();
561
562#if defined(OS_TRACE_RTOS_EVFLAGS)
563 trace::printf ("%s(0x%X) @%p %s >0x%X\n", __func__, mask, this, name (),
564 event_flags_.mask ());
565#endif
566 return res;
567
568#endif
569 }
570
576 {
577#if defined(OS_TRACE_RTOS_EVFLAGS)
578 trace::printf ("%s(0x%X) @%p %s <0x%X \n", __func__, mask, this, name (),
579 event_flags_.mask ());
580#endif
581
582#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
583
584 os_assert_err (mask != 0, EINVAL);
585
586 return port::event_flags::clear (this, mask, oflags);
587
588#else
589
590 result_t res = event_flags_.clear (mask, oflags);
591
592#if defined(OS_TRACE_RTOS_EVFLAGS)
593 trace::printf ("%s(0x%X) @%p %s >0x%X\n", __func__, mask, this, name (),
594 event_flags_.mask ());
595#endif
596
597 return res;
598
599#endif
600 }
601
615 {
616#if defined(OS_TRACE_RTOS_EVFLAGS)
617 trace::printf ("%s(0x%X) @%p %s \n", __func__, mask, this, name ());
618#endif
619
620#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
621
622 return port::event_flags::get (this, mask, mode);
623
624#else
625
626 flags::mask_t ret = event_flags_.get (mask, mode);
627
628#if defined(OS_TRACE_RTOS_EVFLAGS)
629 trace::printf ("%s(0x%X)=0x%X @%p %s \n", __func__, mask,
630 event_flags_.mask (), this, name ());
631#endif
632 // Return the selected flags.
633 return ret;
634
635#endif
636 }
637
641 bool
643 {
644#if defined(OS_TRACE_RTOS_EVFLAGS)
645 trace::printf ("%s() @%p %s\n", __func__, this, name ());
646#endif
647
648#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
649
650 return port::event_flags::waiting (this);
651
652#else
653
654 // Don't call this from high priority interrupts.
655 assert (port::interrupts::is_priority_valid ());
656
657 {
658 // ----- Enter critical section ---------------------------------------
660
661 return !list_.empty ();
662 // ----- Exit critical section ----------------------------------------
663 }
664
665#endif
666 }
667
668 // ------------------------------------------------------------------------
669
670 } /* namespace rtos */
671} /* namespace os */
672
673// ----------------------------------------------------------------------------
Event flags attributes.
Definition os-evflags.h:67
Synchronised event flags.
Definition os-evflags.h:57
result_t wait(flags::mask_t mask, flags::mask_t *oflags, flags::mode_t mode=flags::mode::all|flags::mode::clear)
Wait for event flags.
result_t timed_wait(flags::mask_t mask, clock::duration_t timeout, flags::mask_t *oflags=nullptr, flags::mode_t mode=flags::mode::all|flags::mode::clear)
Timed wait for event flags.
~event_flags()
Destruct the event flags object instance.
event_flags(const attributes &attr=initializer)
Construct an event flags object instance.
bool waiting(void)
Check if there are threads waiting.
flags::mask_t get(flags::mask_t mask, flags::mode_t mode=flags::mode::clear)
Get (and possibly clear) event flags.
result_t try_wait(flags::mask_t mask, flags::mask_t *oflags=nullptr, flags::mode_t mode=flags::mode::all|flags::mode::clear)
Try to wait for event flags.
result_t raise(flags::mask_t mask, flags::mask_t *oflags=nullptr)
Raise event flags.
result_t clear(flags::mask_t mask, flags::mask_t *oflags=nullptr)
Clear event flags.
rtos::clock * clock
Attribute with the address of the clock to be used for timeouts.
Definition os-decls.h:612
Ordered list of time stamp nodes.
Definition os-lists.h:666
const char * name(void) const
Get object name.
Definition os-decls.h:753
Double linked list node, with time stamp and thread.
Definition os-lists.h:220
Double linked list node, with thread reference.
Definition os-lists.h:59
Interrupts critical section RAII helper.
Definition os-sched.h:502
POSIX compliant thread, using the default RTOS allocator.
Definition os-thread.h:251
bool interrupted(void)
Check if interrupted.
Definition os-thread.h:2373
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:78
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:88
clock_systick sysclock
The system clock object instance.
static const attributes initializer
Default event flags initialiser.
Definition os-evflags.h:119
uint32_t mode_t
Type of variables holding flags modes.
Definition os-decls.h:277
uint32_t mask_t
Type of variables holding flags masks.
Definition os-decls.h:266
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1101
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:179
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:858
thread & thread(void)
Get the current running thread.
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:95
System namespace.
#define os_assert_throw(__e, __er)
Assert or throw a system error exception.
Definition os-decls.h:1122
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1101
Single file µOS++ RTOS definitions.