33#pragma clang diagnostic ignored "-Wc++98-compat"
347#if defined(OS_TRACE_RTOS_MQUEUE)
356#if defined(OS_TRACE_RTOS_MQUEUE)
357 trace::printf (
"%s() @%p %s\n", __func__,
this, this->name ());
394 message_queue::message_queue (std::size_t msgs, std::size_t msg_size_bytes,
398 {
nullptr, msgs, msg_size_bytes, attr, allocator }
433 std::size_t msg_size_bytes,
439#if defined(OS_TRACE_RTOS_MQUEUE)
440 trace::printf (
"%s() @%p %s %u %u\n", __func__,
this, this->name (), msgs,
444 if (attr.mq_queue_address !=
nullptr)
447 internal_construct_ (msgs, msg_size_bytes, attr,
nullptr, 0);
451 allocator_ = &allocator;
455 allocated_queue_size_elements_ = (compute_allocated_size_bytes<
456 typename allocator_type::value_type> (msgs, msg_size_bytes)
457 +
sizeof(
typename allocator_type::value_type) - 1)
458 /
sizeof(
typename allocator_type::value_type);
460 allocated_queue_addr_ =
461 const_cast<allocator_type&
> (allocator).allocate (
462 allocated_queue_size_elements_);
464 internal_construct_ (
468 allocated_queue_addr_,
469 allocated_queue_size_elements_
470 *
sizeof(
typename allocator_type::value_type));
490#if defined(OS_TRACE_RTOS_MQUEUE)
494#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
497 assert(send_list_.empty ());
498 assert(receive_list_.empty ());
502 if (allocated_queue_addr_ !=
nullptr)
504 typedef typename std::allocator_traits<allocator_type>::pointer pointer;
507 reinterpret_cast<pointer
> (allocated_queue_addr_),
508 allocated_queue_size_elements_);
511#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
513 port::message_queue::destroy (
this);
523 message_queue::internal_construct_ (std::size_t msgs,
524 std::size_t msg_size_bytes,
525 const attributes& attr,
527 std::size_t queue_size_bytes)
532#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
533 clock_ = attr.clock !=
nullptr ? attr.clock : &
sysclock;
536 assert(msg_size_bytes_ == msg_size_bytes);
537 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 = compute_allocated_size_bytes<void*> (
569 msgs, msg_size_bytes);
571 if (queue_addr_ !=
nullptr)
575#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
577 queue_size_bytes_ >= (std::size_t) (msgs * msg_size_bytes),
585#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
588 port::message_queue::create (
this);
599 reinterpret_cast<index_t*
> (
static_cast<char*
> (queue_addr_)
601 * ((msg_size_bytes + (
sizeof(
void*) - 1))
602 & ~(
sizeof(
void*) - 1)));
605 reinterpret_cast<index_t*
> (
reinterpret_cast<char*
> (
const_cast<index_t*
> (prev_array_))
609 reinterpret_cast<priority_t*
> (
reinterpret_cast<char*
> (
const_cast<index_t*
> (next_array_))
614 reinterpret_cast<char*
> (
reinterpret_cast<char*
> (
const_cast<priority_t*
> (prio_array_))
618 p -
static_cast<char*
> (queue_addr_)
619 <=
static_cast<ptrdiff_t
> (queue_size_bytes_));
627 message_queue::internal_init_ (
void)
631#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
637 char* p =
static_cast<char*
> (queue_addr_);
638 for (std::size_t i = 1; i < msgs_; ++i)
641 char* pn = p + msg_size_bytes_;
644 *(
static_cast<void**
> (
static_cast<void*
> (p))) = pn;
650 *(
static_cast<void**
> (
static_cast<void*
> (p))) =
nullptr;
652 first_free_ = queue_addr_;
660 send_list_.resume_all ();
661 receive_list_.resume_all ();
667#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
674 message_queue::internal_try_send_ (
const void* msg, std::size_t nbytes,
677 if (first_free_ ==
nullptr)
688 char* dest =
static_cast<char*
> (first_free_);
691 first_free_ = *(
static_cast<void**
> (first_free_));
699 std::memcpy (dest, msg, nbytes);
700 if (nbytes < msg_size_bytes_)
703 std::memset (dest + nbytes, 0x00, msg_size_bytes_ - nbytes);
711 std::size_t msg_ix = (
static_cast<std::size_t
> (dest
712 -
static_cast<char*
> (queue_addr_)) / msg_size_bytes_);
713 prio_array_[msg_ix] = mprio;
719 head_ =
static_cast<index_t> (msg_ix);
720 prev_array_[msg_ix] =
static_cast<index_t> (msg_ix);
721 next_array_[msg_ix] =
static_cast<index_t> (msg_ix);
727 ix = prev_array_[head_];
729 if (mprio > prio_array_[head_])
733 head_ =
static_cast<index_t> (msg_ix);
739 while ((mprio > prio_array_[ix]))
741 ix = prev_array_[ix];
744 prev_array_[msg_ix] =
static_cast<index_t> (ix);
745 next_array_[msg_ix] = next_array_[ix];
748 std::size_t tmp_ix = next_array_[ix];
749 next_array_[ix] =
static_cast<index_t> (msg_ix);
750 prev_array_[tmp_ix] =
static_cast<index_t> (msg_ix);
757 receive_list_.resume_one ();
764#if !defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
771 message_queue::internal_try_receive_ (
void* msg, std::size_t nbytes,
781 char* src =
static_cast<char*
> (queue_addr_) + head_ * msg_size_bytes_;
784#if defined(OS_TRACE_RTOS_MQUEUE_)
785 trace::printf (
"%s(%p,%u) @%p %s src %p %p\n", __func__, msg, nbytes,
786 this,
name (), src, first_free_);
794 prev_array_[next_array_[head_]] = prev_array_[head_];
795 next_array_[prev_array_[head_]] = next_array_[head_];
798 head_ = next_array_[head_];
811 interrupts::uncritical_section iucs;
814 memcpy (msg, src, nbytes);
815 if (mprio !=
nullptr)
829 *(
static_cast<void**
> (
static_cast<void*
> (src))) = first_free_;
835 send_list_.resume_one ();
887#if defined(OS_TRACE_RTOS_MQUEUE)
888 trace::printf (
"%s(%p,%d,%d) @%p %s\n", __func__, msg, nbytes, mprio,
900#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
902 return port::message_queue::send (
this, msg, nbytes, mprio);
910 if (internal_try_send_ (msg, nbytes, mprio))
931 if (internal_try_send_ (msg, nbytes, mprio))
937 scheduler::internal_link_node (send_list_, node);
946 scheduler::internal_unlink_node (node);
950#if defined(OS_TRACE_RTOS_MQUEUE)
952 nbytes, mprio,
this,
name ());
959 return ENOTRECOVERABLE;
999#if defined(OS_TRACE_RTOS_MQUEUE)
1000 trace::printf (
"%s(%p,%u,%u) @%p %s\n", __func__, msg, nbytes, mprio,
1007#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1009 return port::message_queue::try_send (
this, msg, nbytes, mprio);
1013 assert(port::interrupts::is_priority_valid ());
1019 if (internal_try_send_ (msg, nbytes, mprio))
1083#if defined(OS_TRACE_RTOS_MQUEUE)
1084 trace::printf (
"%s(%p,%u,%u,%u) @%p %s\n", __func__, msg, nbytes, mprio,
1085 timeout,
this,
name ());
1096#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1098 return port::message_queue::timed_send (
this, msg, nbytes, timeout, mprio);
1108 if (internal_try_send_ (msg, nbytes, mprio))
1129 { timeout_timestamp, crt_thread };
1137 if (internal_try_send_ (msg, nbytes, mprio))
1144 scheduler::internal_link_node (send_list_, node, clock_list,
1155 scheduler::internal_unlink_node (node, timeout_node);
1159#if defined(OS_TRACE_RTOS_MQUEUE)
1160 trace::printf (
"%s(%p,%u,%u,%u) EINTR @%p %s\n", __func__, msg,
1161 nbytes, mprio, timeout,
this,
name ());
1166 if (clock_->steady_now () >= timeout_timestamp)
1168#if defined(OS_TRACE_RTOS_MQUEUE)
1169 trace::printf (
"%s(%p,%u,%u,%u) ETIMEDOUT @%p %s\n", __func__,
1170 msg, nbytes, mprio, timeout,
this,
name ());
1177 return ENOTRECOVERABLE;
1219#if defined(OS_TRACE_RTOS_MQUEUE)
1220 trace::printf (
"%s(%p,%u) @%p %s\n", __func__, msg, nbytes,
this,
1232#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1234 return port::message_queue::receive (
this, msg, nbytes, mprio);
1244 if (internal_try_receive_ (msg, nbytes, mprio))
1265 if (internal_try_receive_ (msg, nbytes, mprio))
1271 scheduler::internal_link_node (receive_list_, node);
1280 scheduler::internal_unlink_node (node);
1284#if defined(OS_TRACE_RTOS_MQUEUE)
1285 trace::printf (
"%s(%p,%u) EINTR @%p %s\n", __func__, msg, nbytes,
1293 return ENOTRECOVERABLE;
1332#if defined(OS_TRACE_RTOS_MQUEUE)
1333 trace::printf (
"%s(%p,%u) @%p %s\n", __func__, msg, nbytes,
this,
1340#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1342 return port::message_queue::try_receive (
this, msg, nbytes, mprio);
1347 assert(port::interrupts::is_priority_valid ());
1353 if (internal_try_receive_ (msg, nbytes, mprio))
1430#if defined(OS_TRACE_RTOS_MQUEUE)
1431 trace::printf (
"%s(%p,%u,%u) @%p %s\n", __func__, msg, nbytes, timeout,
1443#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1445 return port::message_queue::timed_receive (
this, msg, nbytes,
1456 if (internal_try_receive_ (msg, nbytes, mprio))
1476 { timeout_timestamp, crt_thread };
1484 if (internal_try_receive_ (msg, nbytes, mprio))
1491 scheduler::internal_link_node (receive_list_, node, clock_list,
1502 scheduler::internal_unlink_node (node, timeout_node);
1506#if defined(OS_TRACE_RTOS_MQUEUE)
1507 trace::printf (
"%s(%p,%u,%u) EINTR @%p %s\n", __func__, msg,
1508 nbytes, timeout,
this,
name ());
1513 if (clock_->steady_now () >= timeout_timestamp)
1515#if defined(OS_TRACE_RTOS_MQUEUE)
1516 trace::printf (
"%s(%p,%u,%u) ETIMEDOUT @%p %s\n", __func__, msg,
1517 nbytes, timeout,
this,
name ());
1524 return ENOTRECOVERABLE;
1542#if defined(OS_TRACE_RTOS_MQUEUE)
1549#if defined(OS_USE_RTOS_PORT_MESSAGE_QUEUE)
1551 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.