12#if defined(OS_USE_OS_APP_CONFIG_H)
13#include <cmsis-plus/os-app-config.h>
21#pragma clang diagnostic ignored "-Wc++98-compat"
349#if defined(OS_TRACE_RTOS_MQUEUE)
350 trace::printf (
"%s() @%p %s\n", __func__,
this, this->name ());
355 : object_named_system{ name }
357#if defined(OS_TRACE_RTOS_MQUEUE)
358 trace::printf (
"%s() @%p %s\n", __func__,
this, this->name ());
398 :
message_queue{ nullptr, msgs, msg_size_bytes, attr, allocator }
432 std::size_t msg_size_bytes,
435 : object_named_system{ name }
437#if defined(OS_TRACE_RTOS_MQUEUE)
438 trace::printf (
"%s() @%p %s %u %u\n", __func__,
this, this->name (),
439 msgs, msg_size_bytes);
445 internal_construct_ (msgs, msg_size_bytes, attr,
nullptr, 0);
449 allocator_ = &allocator;
453 allocated_queue_size_elements_
460 allocated_queue_addr_
462 allocated_queue_size_elements_);
464 internal_construct_ (
465 msgs, msg_size_bytes, attr, allocated_queue_addr_,
466 allocated_queue_size_elements_
487#if defined(OS_TRACE_RTOS_MQUEUE)
491#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
494 assert (send_list_.empty ());
495 assert (receive_list_.empty ());
499 if (allocated_queue_addr_ !=
nullptr)
502 typename std::allocator_traits<allocator_type>::pointer pointer;
505 ->
deallocate (
reinterpret_cast<pointer
> (allocated_queue_addr_),
506 allocated_queue_size_elements_);
509#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
511 port::message_queue::destroy (
this);
521 message_queue::internal_construct_ (std::size_t msgs,
522 std::size_t msg_size_bytes,
523 const attributes& attr,
525 std::size_t queue_size_bytes)
530#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
531 clock_ = attr.clock !=
nullptr ? attr.clock : &
sysclock;
535 assert (msg_size_bytes_ == msg_size_bytes);
536 assert (msg_size_bytes_ > 0);
541 assert (msg_size_bytes_ >=
sizeof (
void*));
544 assert (msgs_ == msgs);
548 if (queue_address !=
nullptr)
551 assert (attr.mq_queue_address ==
nullptr);
553 queue_addr_ = queue_address;
554 queue_size_bytes_ = queue_size_bytes;
558 queue_addr_ = attr.mq_queue_address;
559 queue_size_bytes_ = attr.mq_queue_size_bytes;
562#if defined(OS_TRACE_RTOS_MQUEUE)
564 msgs_, msg_size_bytes_, queue_addr_, queue_size_bytes_);
567#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
568 std::size_t storage_size
569 = compute_allocated_size_bytes<void*> (msgs, msg_size_bytes);
571 if (queue_addr_ !=
nullptr)
575#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
577 >= (std::size_t)(msgs * msg_size_bytes),
585#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
588 port::message_queue::create (
this);
597#pragma GCC diagnostic push
598#if defined(__clang__)
599#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
602 prev_array_ =
reinterpret_cast<index_t*
> (
603 static_cast<char*
> (queue_addr_)
605 * ((msg_size_bytes + (
sizeof (
void*) - 1))
606 & ~(
sizeof (
void*) - 1)));
608 next_array_ =
reinterpret_cast<index_t*
> (
609 reinterpret_cast<char*
> (
const_cast<index_t*
> (prev_array_))
613 reinterpret_cast<char*
> (
const_cast<index_t*
> (next_array_))
615#pragma GCC diagnostic pop
618#pragma GCC diagnostic push
619#if defined(__clang__)
620#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
621#elif defined(__GNUC__)
622#pragma GCC diagnostic ignored "-Wuseless-cast"
624 char* p =
reinterpret_cast<char*
> (
625 reinterpret_cast<char*
> (
const_cast<priority_t*
> (prio_array_))
627#pragma GCC diagnostic pop
629 assert (p -
static_cast<char*
> (queue_addr_)
630 <=
static_cast<ptrdiff_t
> (queue_size_bytes_));
638 message_queue::internal_init_ (
void)
642#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
648#pragma GCC diagnostic push
649#if defined(__clang__)
650#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
652 char* p =
static_cast<char*
> (queue_addr_);
653 for (std::size_t i = 1; i < msgs_; ++i)
656 char* pn = p + msg_size_bytes_;
659 *(
static_cast<void**
> (
static_cast<void*
> (p))) = pn;
663#pragma GCC diagnostic pop
666 *(
static_cast<void**
> (
static_cast<void*
> (p))) =
nullptr;
668 first_free_ = queue_addr_;
676 send_list_.resume_all ();
677 receive_list_.resume_all ();
682#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
689 message_queue::internal_try_send_ (
const void* msg, std::size_t nbytes,
692 if (first_free_ ==
nullptr)
703#pragma GCC diagnostic push
704#if defined(__clang__)
705#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
707 char* dest =
static_cast<char*
> (first_free_);
708#pragma GCC diagnostic pop
711 first_free_ = *(
static_cast<void**
> (first_free_));
719 std::memcpy (dest, msg, nbytes);
720 if (nbytes < msg_size_bytes_)
723#pragma GCC diagnostic push
724#if defined(__clang__)
725#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
727 std::memset (dest + nbytes, 0x00, msg_size_bytes_ - nbytes);
728#pragma GCC diagnostic pop
735#pragma GCC diagnostic push
736#if defined(__clang__)
737#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
741 = (
static_cast<std::size_t
> (dest -
static_cast<char*
> (queue_addr_))
743 prio_array_[msg_ix] = mprio;
749 head_ =
static_cast<index_t> (msg_ix);
750 prev_array_[msg_ix] =
static_cast<index_t> (msg_ix);
751 next_array_[msg_ix] =
static_cast<index_t> (msg_ix);
757 ix = prev_array_[head_];
759 if (mprio > prio_array_[head_])
763 head_ =
static_cast<index_t> (msg_ix);
769 while ((mprio > prio_array_[ix]))
771 ix = prev_array_[ix];
774 prev_array_[msg_ix] =
static_cast<index_t> (ix);
775 next_array_[msg_ix] = next_array_[ix];
778 std::size_t tmp_ix = next_array_[ix];
779 next_array_[ix] =
static_cast<index_t> (msg_ix);
780 prev_array_[tmp_ix] =
static_cast<index_t> (msg_ix);
782#pragma GCC diagnostic pop
788 receive_list_.resume_one ();
795#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
802 message_queue::internal_try_receive_ (
void* msg, std::size_t nbytes,
812#pragma GCC diagnostic push
813#if defined(__clang__)
814#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
816 char* src =
static_cast<char*
> (queue_addr_) + head_ * msg_size_bytes_;
818#pragma GCC diagnostic pop
820#if defined(OS_TRACE_RTOS_MQUEUE_)
821 trace::printf (
"%s(%p,%u) @%p %s src %p %p\n", __func__, msg, nbytes,
822 this,
name (), src, first_free_);
830#pragma GCC diagnostic push
831#if defined(__clang__)
832#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
834 prev_array_[next_array_[head_]] = prev_array_[head_];
835 next_array_[prev_array_[head_]] = next_array_[head_];
838 head_ = next_array_[head_];
839#pragma GCC diagnostic pop
852 interrupts::uncritical_section iucs;
855 memcpy (msg, src, nbytes);
856 if (mprio !=
nullptr)
870 *(
static_cast<void**
> (
static_cast<void*
> (src))) = first_free_;
876 send_list_.resume_one ();
931#if defined(OS_TRACE_RTOS_MQUEUE)
932 trace::printf (
"%s(%p,%d,%d) @%p %s\n", __func__, msg, nbytes, mprio,
944#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
946 return port::message_queue::send (
this, msg, nbytes, mprio);
954 if (internal_try_send_ (msg, nbytes, mprio))
974 if (internal_try_send_ (msg, nbytes, mprio))
980 scheduler::internal_link_node (send_list_, node);
989 scheduler::internal_unlink_node (node);
993#if defined(OS_TRACE_RTOS_MQUEUE)
995 nbytes, mprio,
this,
name ());
1002 return ENOTRECOVERABLE;
1045#if defined(OS_TRACE_RTOS_MQUEUE)
1046 trace::printf (
"%s(%p,%u,%u) @%p %s\n", __func__, msg, nbytes, mprio,
1053#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1055 return port::message_queue::try_send (
this, msg, nbytes, mprio);
1059 assert (port::interrupts::is_priority_valid ());
1065 if (internal_try_send_ (msg, nbytes, mprio))
1132#if defined(OS_TRACE_RTOS_MQUEUE)
1133 trace::printf (
"%s(%p,%u,%u,%u) @%p %s\n", __func__, msg, nbytes, mprio,
1134 timeout,
this,
name ());
1145#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1147 return port::message_queue::timed_send (
this, msg, nbytes, timeout,
1158 if (internal_try_send_ (msg, nbytes, mprio))
1186 if (internal_try_send_ (msg, nbytes, mprio))
1193 scheduler::internal_link_node (send_list_, node, clock_list,
1204 scheduler::internal_unlink_node (node, timeout_node);
1208#if defined(OS_TRACE_RTOS_MQUEUE)
1209 trace::printf (
"%s(%p,%u,%u,%u) EINTR @%p %s\n", __func__, msg,
1210 nbytes, mprio, timeout,
this,
name ());
1215 if (clock_->steady_now () >= timeout_timestamp)
1217#if defined(OS_TRACE_RTOS_MQUEUE)
1218 trace::printf (
"%s(%p,%u,%u,%u) ETIMEDOUT @%p %s\n", __func__,
1219 msg, nbytes, mprio, timeout,
this,
name ());
1226 return ENOTRECOVERABLE;
1271#if defined(OS_TRACE_RTOS_MQUEUE)
1272 trace::printf (
"%s(%p,%u) @%p %s\n", __func__, msg, nbytes,
this,
1284#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1286 return port::message_queue::receive (
this, msg, nbytes, mprio);
1296 if (internal_try_receive_ (msg, nbytes, mprio))
1316 if (internal_try_receive_ (msg, nbytes, mprio))
1322 scheduler::internal_link_node (receive_list_, node);
1331 scheduler::internal_unlink_node (node);
1335#if defined(OS_TRACE_RTOS_MQUEUE)
1336 trace::printf (
"%s(%p,%u) EINTR @%p %s\n", __func__, msg, nbytes,
1344 return ENOTRECOVERABLE;
1386#if defined(OS_TRACE_RTOS_MQUEUE)
1387 trace::printf (
"%s(%p,%u) @%p %s\n", __func__, msg, nbytes,
this,
1394#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1396 return port::message_queue::try_receive (
this, msg, nbytes, mprio);
1401 assert (port::interrupts::is_priority_valid ());
1407 if (internal_try_receive_ (msg, nbytes, mprio))
1487#if defined(OS_TRACE_RTOS_MQUEUE)
1488 trace::printf (
"%s(%p,%u,%u) @%p %s\n", __func__, msg, nbytes, timeout,
1500#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1502 return port::message_queue::timed_receive (
this, msg, nbytes, timeout,
1513 if (internal_try_receive_ (msg, nbytes, mprio))
1540 if (internal_try_receive_ (msg, nbytes, mprio))
1547 scheduler::internal_link_node (receive_list_, node, clock_list,
1558 scheduler::internal_unlink_node (node, timeout_node);
1562#if defined(OS_TRACE_RTOS_MQUEUE)
1563 trace::printf (
"%s(%p,%u,%u) EINTR @%p %s\n", __func__, msg,
1564 nbytes, timeout,
this,
name ());
1569 if (clock_->steady_now () >= timeout_timestamp)
1571#if defined(OS_TRACE_RTOS_MQUEUE)
1572 trace::printf (
"%s(%p,%u,%u) ETIMEDOUT @%p %s\n", __func__, msg,
1573 nbytes, timeout,
this,
name ());
1580 return ENOTRECOVERABLE;
1598#if defined(OS_TRACE_RTOS_MQUEUE)
1605#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1607 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.
T value_type
Type of elements to be allocated.
Message queue attributes.
void * mq_queue_address
Address of the user defined storage for the message queue.
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.
constexpr std::size_t compute_allocated_size_bytes(std::size_t msgs, std::size_t msg_size_bytes)
Calculator for queue storage requirements.
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.