µ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++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2016 Liviu Ionescu.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <cmsis-plus/rtos/os.h>
29
30// ----------------------------------------------------------------------------
31
32#if defined(__clang__)
33#pragma clang diagnostic ignored "-Wc++98-compat"
34#endif
35
36// ----------------------------------------------------------------------------
37
38namespace os
39{
40 namespace rtos
41 {
42 // ------------------------------------------------------------------------
43
62 const event_flags::attributes event_flags::initializer;
63
64 // ------------------------------------------------------------------------
65
139 { nullptr, attr }
140 {
141 ;
142 }
143
144#pragma GCC diagnostic push
145#pragma GCC diagnostic ignored "-Wunused-parameter"
146
171 event_flags::event_flags (const char* name, const attributes& attr) :
172 object_named_system
173 { name }
174 {
175#if defined(OS_TRACE_RTOS_EVFLAGS)
176 trace::printf ("%s() @%p %s\n", __func__, this, this->name ());
177#endif
178
179 // Don't call this from interrupt handlers.
181
182#if !defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
183 clock_ = attr.clock != nullptr ? attr.clock : &sysclock;
184#endif
185
186#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
187
188 port::event_flags::create (this);
189
190#else
191
192#endif
193
194 }
195
196#pragma GCC diagnostic pop
197
212 {
213#if defined(OS_TRACE_RTOS_EVFLAGS)
214 trace::printf ("%s() @%p %s\n", __func__, this, name ());
215#endif
216
217#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
218
219 port::event_flags::destroy (this);
220
221#else
222
223 // There must be no threads waiting for these flags.
224 assert(list_.empty ());
225
226#endif
227 }
228
252 flags::mode_t mode)
253 {
254#if defined(OS_TRACE_RTOS_EVFLAGS)
255 trace::printf ("%s(0x%X,%u) @%p %s <0x%X\n", __func__, mask, mode, this,
256 name (), event_flags_.mask ());
257#endif
258
259 // Don't call this from interrupt handlers.
261 // Don't call this from critical regions.
263
264#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
265
266 return port::event_flags::wait (this, mask, oflags, mode);
267
268#else
269
270 {
271 // ----- Enter critical section -------------------------------------
273
274 if (event_flags_.check_raised (mask, oflags, mode))
275 {
276#if defined(OS_TRACE_RTOS_EVFLAGS)
277 trace::printf ("%s(0x%X,%u) @%p %s >0x%X\n", __func__, mask, mode,
278 this, name (), event_flags_.mask ());
279#endif
280 return result::ok;
281 }
282 // ----- Exit critical section --------------------------------------
283 }
284
285 thread& crt_thread = this_thread::thread ();
286
287 // Prepare a list node pointing to the current thread.
288 // Do not worry for being on stack, it is temporarily linked to the
289 // list and guaranteed to be removed before this function returns.
291 { crt_thread };
292
293 for (;;)
294 {
295 {
296 // ----- Enter critical section ---------------------------------
298
299 if (event_flags_.check_raised (mask, oflags, mode))
300 {
301#if defined(OS_TRACE_RTOS_EVFLAGS)
302 trace::printf ("%s(0x%X,%u) @%p %s >0x%X\n", __func__, mask,
303 mode, this, name (), event_flags_.mask ());
304#endif
305 return result::ok;
306 }
307
308 // Add this thread to the event flags waiting list.
309 scheduler::internal_link_node (list_, node);
310 // state::suspended set in above link().
311 // ----- Exit critical section ----------------------------------
312 }
313
315
316 {
317 // ----- Enter critical section ---------------------------------
319
320 // Remove the thread from the event flags waiting list,
321 // if not already removed by raise().
322 scheduler::internal_unlink_node (node);
323 // ----- Exit critical section ----------------------------------
324 }
325
326 if (crt_thread.interrupted ())
327 {
328#if defined(OS_TRACE_RTOS_EVFLAGS)
329 trace::printf ("%s(0x%X,%u) EINTR @%p %s\n", __func__, mask, mode,
330 this, name ());
331#endif
332 return EINTR;
333 }
334 }
335
336 /* NOTREACHED */
337 return ENOTRECOVERABLE;
338
339#endif
340 }
341
355 flags::mode_t mode)
356 {
357#if defined(OS_TRACE_RTOS_EVFLAGS)
358 trace::printf ("%s(0x%X,%u) @%p %s <0x%X\n", __func__, mask, mode, this,
359 name (), event_flags_.mask ());
360#endif
361
362#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
363
364 return port::event_flags::try_wait (this, mask, oflags, mode);
365
366#else
367
368 // Don't call this from high priority interrupts.
369 assert(port::interrupts::is_priority_valid ());
370
371 {
372 // ----- Enter critical section -------------------------------------
374
375 if (event_flags_.check_raised (mask, oflags, mode))
376 {
377#if defined(OS_TRACE_RTOS_EVFLAGS)
378 trace::printf ("%s(0x%X,%u) @%p %s >0x%X\n", __func__, mask, mode,
379 this, name (), event_flags_.mask ());
380#endif
381 return result::ok;
382 }
383 else
384 {
385#if defined(OS_TRACE_RTOS_EVFLAGS)
386 trace::printf ("%s(0x%X,%u) EWOULDBLOCK @%p %s \n", __func__,
387 mask, mode, this, name ());
388#endif
389 return EWOULDBLOCK;
390 }
391 // ----- Exit critical section --------------------------------------
392 }
393
394#endif
395 }
396
437 flags::mask_t* oflags, flags::mode_t mode)
438 {
439#if defined(OS_TRACE_RTOS_EVFLAGS)
440 trace::printf ("%s(0x%X,%u,%u) @%p %s <0x%X\n", __func__, mask, timeout,
441 mode, this, name (), event_flags_.mask ());
442#endif
443
444 // Don't call this from interrupt handlers.
446 // Don't call this from critical regions.
448
449#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
450
451 return port::event_flags::timed_wait (this, mask, timeout, oflags, mode);
452
453#else
454
455 // Extra test before entering the loop, with its inherent weight.
456 // Trade size for speed.
457 {
458 // ----- Enter critical section -------------------------------------
460
461 if (event_flags_.check_raised (mask, oflags, mode))
462 {
463#if defined(OS_TRACE_RTOS_EVFLAGS)
464 trace::printf ("%s(0x%X,%u,%u) @%p %s >0x%X\n", __func__, mask,
465 timeout, mode, this, name (),
466 event_flags_.mask ());
467#endif
468 return result::ok;
469 }
470 // ----- Exit critical section --------------------------------------
471 }
472
473 thread& crt_thread = this_thread::thread ();
474
475 // Prepare a list node pointing to the current thread.
476 // Do not worry for being on stack, it is temporarily linked to the
477 // list and guaranteed to be removed before this function returns.
479 { crt_thread };
480
481 internal::clock_timestamps_list& clock_list = clock_->steady_list ();
482 clock::timestamp_t timeout_timestamp = clock_->steady_now () + timeout;
483
484 // Prepare a timeout node pointing to the current thread.
486 { timeout_timestamp, crt_thread };
487
488 for (;;)
489 {
490 {
491 // ----- Enter critical section ---------------------------------
493
494 if (event_flags_.check_raised (mask, oflags, mode))
495 {
496#if defined(OS_TRACE_RTOS_EVFLAGS)
497 trace::printf ("%s(0x%X,%u,%u) @%p %s >0x%X\n", __func__,
498 mask, timeout, mode, this, name (),
499 event_flags_.mask ());
500#endif
501 return result::ok;
502 }
503
504 // Add this thread to the event flags waiting list,
505 // and the clock timeout list.
506 scheduler::internal_link_node (list_, node, clock_list,
507 timeout_node);
508 // state::suspended set in above link().
509 // ----- Exit critical section ----------------------------------
510 }
511
513
514 // Remove the thread from the event flags waiting list,
515 // if not already removed by raise() and from the clock
516 // timeout list, if not already removed by the timer.
517 scheduler::internal_unlink_node (node, timeout_node);
518
519 if (crt_thread.interrupted ())
520 {
521#if defined(OS_TRACE_RTOS_EVFLAGS)
522 trace::printf ("%s(0x%X,%u,%u) EINTR @%p %s 0x%X \n", __func__,
523 mask, timeout, mode, this, name ());
524#endif
525 return EINTR;
526 }
527
528 if (clock_->steady_now () >= timeout_timestamp)
529 {
530#if defined(OS_TRACE_RTOS_EVFLAGS)
531 trace::printf ("%s(0x%X,%u,%u) ETIMEDOUT @%p %s 0x%X \n",
532 __func__, mask, timeout, mode, this, name ());
533#endif
534 return ETIMEDOUT;
535 }
536 }
537
538 /* NOTREACHED */
539 return ENOTRECOVERABLE;
540
541#endif
542 }
543
554 {
555#if defined(OS_TRACE_RTOS_EVFLAGS)
556 trace::printf ("%s(0x%X) @%p %s <0x%X \n", __func__, mask, this, name (),
557 event_flags_.mask ());
558#endif
559
560#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
561
562 os_assert_err(mask != 0, EINVAL);
563
564 return port::event_flags::raise (this, mask, oflags);
565
566#else
567
568 result_t res = event_flags_.raise (mask, oflags);
569
570 // Wake-up all threads, if any.
571 // Need not be inside the critical section,
572 // the list is protected by inner `resume_one()`.
573 list_.resume_all ();
574
575#if defined(OS_TRACE_RTOS_EVFLAGS)
576 trace::printf ("%s(0x%X) @%p %s >0x%X\n", __func__, mask, this, name (),
577 event_flags_.mask ());
578#endif
579 return res;
580
581#endif
582 }
583
589 {
590#if defined(OS_TRACE_RTOS_EVFLAGS)
591 trace::printf ("%s(0x%X) @%p %s <0x%X \n", __func__, mask, this, name (),
592 event_flags_.mask ());
593#endif
594
595#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
596
597 os_assert_err(mask != 0, EINVAL);
598
599 return port::event_flags::clear (this, mask, oflags);
600
601#else
602
603 result_t res = event_flags_.clear (mask, oflags);
604
605#if defined(OS_TRACE_RTOS_EVFLAGS)
606 trace::printf ("%s(0x%X) @%p %s >0x%X\n", __func__, mask, this, name (),
607 event_flags_.mask ());
608#endif
609
610 return res;
611
612#endif
613 }
614
628 {
629#if defined(OS_TRACE_RTOS_EVFLAGS)
630 trace::printf ("%s(0x%X) @%p %s \n", __func__, mask, this, name ());
631#endif
632
633#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
634
635 return port::event_flags::get (this, mask, mode);
636
637#else
638
639 flags::mask_t ret = event_flags_.get (mask, mode);
640
641#if defined(OS_TRACE_RTOS_EVFLAGS)
642 trace::printf ("%s(0x%X)=0x%X @%p %s \n", __func__, mask,
643 event_flags_.mask (), this, name ());
644#endif
645 // Return the selected flags.
646 return ret;
647
648#endif
649 }
650
654 bool
656 {
657#if defined(OS_TRACE_RTOS_EVFLAGS)
658 trace::printf ("%s() @%p %s\n", __func__, this, name ());
659#endif
660
661#if defined(OS_USE_RTOS_PORT_EVENT_FLAGS)
662
663 return port::event_flags::waiting (this);
664
665#else
666
667 // Don't call this from high priority interrupts.
668 assert(port::interrupts::is_priority_valid ());
669
670 {
671 // ----- Enter critical section -------------------------------------
673
674 return !list_.empty ();
675 // ----- Exit critical section --------------------------------------
676 }
677
678#endif
679 }
680
681 // --------------------------------------------------------------------------
682
683 } /* namespace rtos */
684} /* namespace os */
685
686// ----------------------------------------------------------------------------
Event flags attributes.
Definition os-evflags.h:77
Synchronised event flags.
Definition os-evflags.h:66
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.
Ordered list of time stamp nodes.
Definition os-lists.h:671
const char * name(void) const
Get object name.
Definition os-decls.h:774
Double linked list node, with time stamp and thread.
Definition os-lists.h:227
Double linked list node, with thread reference.
Definition os-lists.h:72
Interrupts critical section RAII helper.
Definition os-sched.h:524
POSIX compliant thread, using the default RTOS allocator.
Definition os-thread.h:247
bool interrupted(void)
Check if interrupted.
Definition os-thread.h:2361
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:74
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:83
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition os-clocks.h:92
clock_systick sysclock
The system clock object instance.
static const attributes initializer
Default event flags initialiser.
Definition os-evflags.h:130
uint32_t mode_t
Type of variables holding flags modes.
Definition os-decls.h:289
uint32_t mask_t
Type of variables holding flags masks.
Definition os-decls.h:279
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition os-sched.h:1136
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:195
bool locked(void)
Check if the scheduler is locked.
Definition os-sched.h:882
thread & thread(void)
Get the current running thread.
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:110
System namespace.
#define os_assert_throw(__e, __er)
Assert or throw a system error exception.
Definition os-decls.h:1141
#define os_assert_err(__e, __er)
Assert or return an error.
Definition os-decls.h:1126
Single file µOS++ RTOS definitions.