13#if defined(OS_USE_OS_APP_CONFIG_H)
14#include <cmsis-plus/os-app-config.h>
22#pragma clang diagnostic ignored "-Wc++98-compat"
336#if defined(OS_TRACE_RTOS_MQUEUE)
345#if defined(OS_TRACE_RTOS_MQUEUE)
346 trace::printf (
"%s() @%p %s\n", __func__,
this, this->name ());
383 message_queue::message_queue (std::size_t msgs, std::size_t msg_size_bytes,
387 {
nullptr, msgs, msg_size_bytes, attr, allocator }
421 std::size_t msg_size_bytes,
427#if defined(OS_TRACE_RTOS_MQUEUE)
428 trace::printf (
"%s() @%p %s %u %u\n", __func__,
this, this->name (), msgs,
432 if (attr.mq_queue_address !=
nullptr)
435 internal_construct_ (msgs, msg_size_bytes, attr,
nullptr, 0);
439 allocator_ = &allocator;
443 allocated_queue_size_elements_ = (compute_allocated_size_bytes<
444 typename allocator_type::value_type> (msgs, msg_size_bytes)
445 +
sizeof(
typename allocator_type::value_type) - 1)
446 /
sizeof(
typename allocator_type::value_type);
448 allocated_queue_addr_ =
449 const_cast<allocator_type&
> (allocator).allocate (
450 allocated_queue_size_elements_);
452 internal_construct_ (
456 allocated_queue_addr_,
457 allocated_queue_size_elements_
458 *
sizeof(
typename allocator_type::value_type));
478#if defined(OS_TRACE_RTOS_MQUEUE)
482#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
485 assert(send_list_.empty ());
486 assert(receive_list_.empty ());
490 if (allocated_queue_addr_ !=
nullptr)
492 typedef typename std::allocator_traits<allocator_type>::pointer pointer;
495 reinterpret_cast<pointer
> (allocated_queue_addr_),
496 allocated_queue_size_elements_);
499#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
501 port::message_queue::destroy (
this);
511 message_queue::internal_construct_ (std::size_t msgs,
512 std::size_t msg_size_bytes,
513 const attributes& attr,
515 std::size_t queue_size_bytes)
520#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
521 clock_ = attr.clock !=
nullptr ? attr.clock : &
sysclock;
524 assert(msg_size_bytes_ == msg_size_bytes);
525 assert(msg_size_bytes_ > 0);
529 assert(msg_size_bytes_ >=
sizeof(
void*));
532 assert(msgs_ == msgs);
536 if (queue_address !=
nullptr)
539 assert(attr.mq_queue_address ==
nullptr);
541 queue_addr_ = queue_address;
542 queue_size_bytes_ = queue_size_bytes;
546 queue_addr_ = attr.mq_queue_address;
547 queue_size_bytes_ = attr.mq_queue_size_bytes;
550#if defined(OS_TRACE_RTOS_MQUEUE)
552 msgs_, msg_size_bytes_, queue_addr_, queue_size_bytes_);
555#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
556 std::size_t storage_size = compute_allocated_size_bytes<void*> (
557 msgs, msg_size_bytes);
559 if (queue_addr_ !=
nullptr)
563#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
565 queue_size_bytes_ >= (std::size_t) (msgs * msg_size_bytes),
573#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
576 port::message_queue::create (
this);
587 reinterpret_cast<index_t*
> (
static_cast<char*
> (queue_addr_)
589 * ((msg_size_bytes + (
sizeof(
void*) - 1))
590 & ~(
sizeof(
void*) - 1)));
593 reinterpret_cast<index_t*
> (
reinterpret_cast<char*
> (
const_cast<index_t*
> (prev_array_))
597 reinterpret_cast<priority_t*
> (
reinterpret_cast<char*
> (
const_cast<index_t*
> (next_array_))
601#pragma GCC diagnostic push
602#if defined(__clang__)
603#elif defined(__GNUC__)
604#pragma GCC diagnostic ignored "-Wuseless-cast"
607 reinterpret_cast<char*
> (
reinterpret_cast<char*
> (
const_cast<priority_t*
> (prio_array_))
609#pragma GCC diagnostic pop
612 p -
static_cast<char*
> (queue_addr_)
613 <=
static_cast<ptrdiff_t
> (queue_size_bytes_));
621 message_queue::internal_init_ (
void)
625#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
631 char* p =
static_cast<char*
> (queue_addr_);
632 for (std::size_t i = 1; i < msgs_; ++i)
635 char* pn = p + msg_size_bytes_;
638 *(
static_cast<void**
> (
static_cast<void*
> (p))) = pn;
644 *(
static_cast<void**
> (
static_cast<void*
> (p))) =
nullptr;
646 first_free_ = queue_addr_;
654 send_list_.resume_all ();
655 receive_list_.resume_all ();
661#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
668 message_queue::internal_try_send_ (
const void* msg, std::size_t nbytes,
671 if (first_free_ ==
nullptr)
682 char* dest =
static_cast<char*
> (first_free_);
685 first_free_ = *(
static_cast<void**
> (first_free_));
693 std::memcpy (dest, msg, nbytes);
694 if (nbytes < msg_size_bytes_)
697 std::memset (dest + nbytes, 0x00, msg_size_bytes_ - nbytes);
705 std::size_t msg_ix = (
static_cast<std::size_t
> (dest
706 -
static_cast<char*
> (queue_addr_)) / msg_size_bytes_);
707 prio_array_[msg_ix] = mprio;
713 head_ =
static_cast<index_t> (msg_ix);
714 prev_array_[msg_ix] =
static_cast<index_t> (msg_ix);
715 next_array_[msg_ix] =
static_cast<index_t> (msg_ix);
721 ix = prev_array_[head_];
723 if (mprio > prio_array_[head_])
727 head_ =
static_cast<index_t> (msg_ix);
733 while ((mprio > prio_array_[ix]))
735 ix = prev_array_[ix];
738 prev_array_[msg_ix] =
static_cast<index_t> (ix);
739 next_array_[msg_ix] = next_array_[ix];
742 std::size_t tmp_ix = next_array_[ix];
743 next_array_[ix] =
static_cast<index_t> (msg_ix);
744 prev_array_[tmp_ix] =
static_cast<index_t> (msg_ix);
751 receive_list_.resume_one ();
758#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
765 message_queue::internal_try_receive_ (
void* msg, std::size_t nbytes,
775 char* src =
static_cast<char*
> (queue_addr_) + head_ * msg_size_bytes_;
778#if defined(OS_TRACE_RTOS_MQUEUE_)
779 trace::printf (
"%s(%p,%u) @%p %s src %p %p\n", __func__, msg, nbytes,
780 this,
name (), src, first_free_);
788 prev_array_[next_array_[head_]] = prev_array_[head_];
789 next_array_[prev_array_[head_]] = next_array_[head_];
792 head_ = next_array_[head_];
805 interrupts::uncritical_section iucs;
808 memcpy (msg, src, nbytes);
809 if (mprio !=
nullptr)
823 *(
static_cast<void**
> (
static_cast<void*
> (src))) = first_free_;
829 send_list_.resume_one ();
881#if defined(OS_TRACE_RTOS_MQUEUE)
882 trace::printf (
"%s(%p,%d,%d) @%p %s\n", __func__, msg, nbytes, mprio,
894#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
896 return port::message_queue::send (
this, msg, nbytes, mprio);
904 if (internal_try_send_ (msg, nbytes, mprio))
925 if (internal_try_send_ (msg, nbytes, mprio))
931 scheduler::internal_link_node (send_list_, node);
940 scheduler::internal_unlink_node (node);
944#if defined(OS_TRACE_RTOS_MQUEUE)
946 nbytes, mprio,
this,
name ());
953 return ENOTRECOVERABLE;
993#if defined(OS_TRACE_RTOS_MQUEUE)
994 trace::printf (
"%s(%p,%u,%u) @%p %s\n", __func__, msg, nbytes, mprio,
1001#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1003 return port::message_queue::try_send (
this, msg, nbytes, mprio);
1007 assert(port::interrupts::is_priority_valid ());
1013 if (internal_try_send_ (msg, nbytes, mprio))
1077#if defined(OS_TRACE_RTOS_MQUEUE)
1078 trace::printf (
"%s(%p,%u,%u,%u) @%p %s\n", __func__, msg, nbytes, mprio,
1079 timeout,
this,
name ());
1090#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1092 return port::message_queue::timed_send (
this, msg, nbytes, timeout, mprio);
1102 if (internal_try_send_ (msg, nbytes, mprio))
1123 { timeout_timestamp, crt_thread };
1131 if (internal_try_send_ (msg, nbytes, mprio))
1138 scheduler::internal_link_node (send_list_, node, clock_list,
1149 scheduler::internal_unlink_node (node, timeout_node);
1153#if defined(OS_TRACE_RTOS_MQUEUE)
1154 trace::printf (
"%s(%p,%u,%u,%u) EINTR @%p %s\n", __func__, msg,
1155 nbytes, mprio, timeout,
this,
name ());
1160 if (clock_->steady_now () >= timeout_timestamp)
1162#if defined(OS_TRACE_RTOS_MQUEUE)
1163 trace::printf (
"%s(%p,%u,%u,%u) ETIMEDOUT @%p %s\n", __func__,
1164 msg, nbytes, mprio, timeout,
this,
name ());
1171 return ENOTRECOVERABLE;
1213#if defined(OS_TRACE_RTOS_MQUEUE)
1214 trace::printf (
"%s(%p,%u) @%p %s\n", __func__, msg, nbytes,
this,
1226#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1228 return port::message_queue::receive (
this, msg, nbytes, mprio);
1238 if (internal_try_receive_ (msg, nbytes, mprio))
1259 if (internal_try_receive_ (msg, nbytes, mprio))
1265 scheduler::internal_link_node (receive_list_, node);
1274 scheduler::internal_unlink_node (node);
1278#if defined(OS_TRACE_RTOS_MQUEUE)
1279 trace::printf (
"%s(%p,%u) EINTR @%p %s\n", __func__, msg, nbytes,
1287 return ENOTRECOVERABLE;
1326#if defined(OS_TRACE_RTOS_MQUEUE)
1327 trace::printf (
"%s(%p,%u) @%p %s\n", __func__, msg, nbytes,
this,
1334#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1336 return port::message_queue::try_receive (
this, msg, nbytes, mprio);
1341 assert(port::interrupts::is_priority_valid ());
1347 if (internal_try_receive_ (msg, nbytes, mprio))
1424#if defined(OS_TRACE_RTOS_MQUEUE)
1425 trace::printf (
"%s(%p,%u,%u) @%p %s\n", __func__, msg, nbytes, timeout,
1437#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1439 return port::message_queue::timed_receive (
this, msg, nbytes,
1450 if (internal_try_receive_ (msg, nbytes, mprio))
1470 { timeout_timestamp, crt_thread };
1478 if (internal_try_receive_ (msg, nbytes, mprio))
1485 scheduler::internal_link_node (receive_list_, node, clock_list,
1496 scheduler::internal_unlink_node (node, timeout_node);
1500#if defined(OS_TRACE_RTOS_MQUEUE)
1501 trace::printf (
"%s(%p,%u,%u) EINTR @%p %s\n", __func__, msg,
1502 nbytes, timeout,
this,
name ());
1507 if (clock_->steady_now () >= timeout_timestamp)
1509#if defined(OS_TRACE_RTOS_MQUEUE)
1510 trace::printf (
"%s(%p,%u,%u) ETIMEDOUT @%p %s\n", __func__, msg,
1511 nbytes, timeout,
this,
name ());
1518 return ENOTRECOVERABLE;
1536#if defined(OS_TRACE_RTOS_MQUEUE)
1543#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1545 return port::message_queue::reset (
this);
Ordered list of time stamp nodes.
const char * name(void) const
Get object name.
Double linked list node, with time stamp and thread.
Double linked list node, with thread reference.
Interrupts critical section RAII helper.
Standard allocator based on the RTOS system default memory manager.
void deallocate(value_type *addr, std::size_t elements) noexcept
Deallocate the number of memory blocks of type value_type.
Message queue attributes.
POSIX compliant message queue, using the default RTOS allocator.
result_t receive(void *msg, std::size_t nbytes, priority_t *mprio=nullptr)
Receive a message from the queue.
result_t reset(void)
Reset the message queue.
result_t try_send(const void *msg, std::size_t nbytes, priority_t mprio=default_priority)
Try to send a message to the queue.
result_t try_receive(void *msg, std::size_t nbytes, priority_t *mprio=nullptr)
Try to receive a message from the queue.
result_t send(const void *msg, std::size_t nbytes, priority_t mprio=default_priority)
Send a message to the queue.
virtual ~message_queue()
Destruct the message queue object instance.
result_t timed_receive(void *msg, std::size_t nbytes, clock::duration_t timeout, priority_t *mprio=nullptr)
Receive a message from the queue with timeout.
result_t timed_send(const void *msg, std::size_t nbytes, clock::duration_t timeout, priority_t mprio=default_priority)
Send a message to the queue with timeout.
message_queue(std::size_t msgs, std::size_t msg_size_bytes, const attributes &attr=initializer, const allocator_type &allocator=allocator_type())
Construct a message queue object instance.
POSIX compliant thread, using the default RTOS allocator.
bool interrupted(void)
Check if interrupted.
int printf(const char *format,...)
Write a formatted string to the trace device.
port::clock::duration_t duration_t
Type of variables holding clock durations.
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
clock_systick sysclock
The system clock object instance.
uint8_t priority_t
Type of message priority storage.
message_queue::size_t index_t
Type of list index storage.
static const attributes initializer
Default message queue initialiser.
uint8_t size_t
Type of a queue size storage.
uint16_t msg_size_t
Type of message size storage.
static constexpr index_t no_index
Index value to represent an illegal index.
bool in_handler_mode(void)
Check if the CPU is in handler mode.
@ ok
Function completed; no errors or events occurred.
bool locked(void)
Check if the scheduler is locked.
thread & thread(void)
Get the current running thread.
uint32_t result_t
Type of values returned by RTOS functions.
#define os_assert_throw(__e, __er)
Assert or throw a system error exception.
#define os_assert_err(__e, __er)
Assert or return an error.
Single file µOS++ RTOS definitions.