10 #include <type_traits> 21 ComQueue ::QueueConfigurationTable ::QueueConfigurationTable() {
22 static_assert(static_cast<FwUnsignedIndexType>(std::numeric_limits<FwIndexType>::max()) >=
24 "Number of entries must fit into FwIndexType");
26 this->entries[i].priority = 0;
27 this->entries[i].depth = 0;
36 m_buffer_state(OWNED),
40 m_allocation(nullptr) {
43 this->m_throttle[i] =
false;
44 this->m_managedDrops[i] = 0;
47 this->m_comIngressDrops[i].store(0, std::memory_order_relaxed);
50 this->m_buffIngressDrops[i].store(0, std::memory_order_relaxed);
53 static_assert(
TOTAL_PORT_COUNT >= 1,
"ComQueue must have more than one port");
60 if ((this->m_allocator !=
nullptr) && (this->m_allocation !=
nullptr)) {
61 this->m_allocator->
deallocate(this->m_allocationId, this->m_allocation);
72 this->m_allocator = &allocator;
73 this->m_allocationId = allocationId;
74 this->m_allocation =
nullptr;
92 static_cast<FwAssertArgType>(
TOTAL_PORT_COUNT), static_cast<FwAssertArgType>(entryIndex));
97 QueueMetadata& entry = this->m_prioritizedList[currentPriorityIndex];
102 entry.index = entryIndex;
108 if (entry.depth > 0) {
109 FW_ASSERT((std::numeric_limits<FwSizeType>::max() / entry.depth) >= entry.msgSize,
110 static_cast<FwAssertArgType>(entry.depth), static_cast<FwAssertArgType>(entry.msgSize));
111 FW_ASSERT(std::numeric_limits<FwSizeType>::max() - (entry.depth * entry.msgSize) >=
113 totalAllocation += entry.depth * entry.msgSize;
115 currentPriorityIndex++;
122 bool recoverable =
false;
123 FwSizeType actualAllocation = totalAllocation;
124 this->m_allocation = this->m_allocator->
allocate(this->m_allocationId, actualAllocation, recoverable);
125 FW_ASSERT(this->m_allocation !=
nullptr);
126 FW_ASSERT(actualAllocation >= totalAllocation, static_cast<FwAssertArgType>(actualAllocation),
127 static_cast<FwAssertArgType>(totalAllocation));
135 FwSizeType allocationSize = this->m_prioritizedList[i].depth * this->m_prioritizedList[i].msgSize;
137 static_cast<FwAssertArgType>(this->m_prioritizedList[i].index));
138 FW_ASSERT((allocationSize + allocationOffset) <= totalAllocation, static_cast<FwAssertArgType>(allocationSize),
139 static_cast<FwAssertArgType>(allocationOffset), static_cast<FwAssertArgType>(totalAllocation));
142 if (this->m_prioritizedList[i].depth > 0) {
143 this->m_queues[this->m_prioritizedList[i].index].
setup(
144 reinterpret_cast<U8*>(this->m_allocation) + allocationOffset, allocationSize,
145 this->m_prioritizedList[i].depth, this->m_prioritizedList[i].msgSize, this->m_prioritizedList[i].mode,
146 this->m_prioritizedList[i].overflowMode);
148 allocationOffset += allocationSize;
151 FW_ASSERT(allocationOffset == totalAllocation, static_cast<FwAssertArgType>(allocationOffset),
152 static_cast<FwAssertArgType>(totalAllocation));
159 void ComQueue ::FLUSH_QUEUE_cmdHandler(
FwOpcodeType opCode,
164 FwIndexType queueIndex = this->getQueueNum(queueType, index);
173 this->drainQueue(queueIndex);
177 void ComQueue ::FLUSH_ALL_QUEUES_cmdHandler(
FwOpcodeType opCode, U32 cmdSeq) {
184 void ComQueue::SET_QUEUE_PRIORITY_cmdHandler(
FwOpcodeType opCode,
190 FwIndexType queueIndex = this->getQueueNum(queueType, index);
208 static_cast<FwAssertArgType>(m_prioritizedList[prioIndex].index));
210 if (m_prioritizedList[prioIndex].index == queueIndex) {
211 m_prioritizedList[prioIndex].priority = newPriority;
220 if (m_prioritizedList[j].priority > m_prioritizedList[j + 1].priority) {
222 QueueMetadata temp = m_prioritizedList[j];
223 m_prioritizedList[j] = m_prioritizedList[j + 1];
224 m_prioritizedList[j + 1] = temp;
243 (void)this->enqueue(portNum, data);
252 bool success = this->enqueue(queueNum, fwBuffer);
259 switch (this->m_state) {
263 this->m_state = READY;
264 this->processQueue();
266 FW_ASSERT((this->m_state == WAITING || this->m_state == READY),
267 static_cast<FwAssertArgType>(this->m_state));
269 this->m_state = WAITING;
275 FW_ASSERT(
false, static_cast<FwAssertArgType>(this->m_state));
280 void ComQueue::run_handler(
const FwIndexType portNum, U32 context) {
281 bool expected =
false;
282 if (this->m_runQueued.compare_exchange_strong(expected,
true)) {
287 void ComQueue::runInternal_overflowHook() {
288 this->m_runQueued =
false;
291 void ComQueue::runInternal_internalInterfaceHandler() {
292 this->m_runQueued =
false;
294 ComQueueDepth comQueueDepth;
296 for (U32 i = 0; i < comQueueDepth.SIZE; i++) {
298 comQueueDepth[i] = 0;
299 if (this->getQueueDepth(queueNum) > 0) {
307 BuffQueueDepth buffQueueDepth;
309 static_cast<FwAssertArgType>(buffQueueDepth.SIZE));
310 for (U32 i = 0; i < buffQueueDepth.SIZE; i++) {
312 buffQueueDepth[i] = 0;
313 if (this->getQueueDepth(queueNum) > 0) {
320 ComQueueIngressDrops comIngressDropped;
322 for (U32 i = 0; i < comIngressDropped.SIZE; i++) {
323 comIngressDropped[i] = this->m_comIngressDrops[i].load(std::memory_order_relaxed);
327 BuffQueueIngressDrops buffIngressDropped;
329 for (U32 i = 0; i < buffIngressDropped.SIZE; i++) {
330 buffIngressDropped[i] = this->m_buffIngressDrops[i].load(std::memory_order_relaxed);
334 ComQueueManagedDrops comManagedDropped;
336 for (U32 i = 0; i < comManagedDropped.SIZE; i++) {
337 comManagedDropped[i] = this->m_managedDrops[i];
341 BuffQueueManagedDrops buffManagedDropped;
343 static_cast<FwAssertArgType>(buffManagedDropped.SIZE));
344 for (U32 i = 0; i < buffManagedDropped.SIZE; i++) {
351 static_assert(std::numeric_limits<FwIndexType>::is_signed,
"FwIndexType must be signed");
353 const BufferState previousState = this->m_buffer_state.exchange(OWNED);
354 FW_ASSERT(previousState == UNOWNED, static_cast<FwAssertArgType>(previousState));
362 if (bufferReturnPortNum >= 0) {
365 static_cast<FwAssertArgType>(bufferReturnPortNum));
379 this->m_comIngressDrops[portNum].fetch_add(1, std::memory_order_relaxed);
384 this->m_buffIngressDrops[portNum].fetch_add(1, std::memory_order_relaxed);
396 if (this->getQueueDepth(queueNum) == 0) {
410 if (this->getQueueDepth(queueNum) == 0) {
418 bool preEmptiveOverflow =
false;
421 if (this->m_prioritizedList[i].index == queueNum &&
423 queue.
getQueueSize() >= this->m_prioritizedList[i].depth) {
431 preEmptiveOverflow =
true;
440 bool ComQueue::handleEnqueueStatus(
const FwIndexType queueNum,
443 const bool preEmptiveOverflow,
447 ++this->m_managedDrops[queueNum];
448 if (!this->m_throttle[queueNum]) {
450 this->m_throttle[queueNum] =
true;
455 if (this->m_state == READY) {
456 this->processQueue();
472 context.
set_apid(static_cast<ComCfg::Apid::T>(descriptor));
474 const BufferState previousState = this->m_buffer_state.exchange(UNOWNED);
475 FW_ASSERT(previousState == OWNED, static_cast<FwAssertArgType>(previousState));
478 this->m_state = WAITING;
490 context.
set_apid(static_cast<ComCfg::Apid::T>(descriptor));
492 const BufferState previousState = this->m_buffer_state.exchange(UNOWNED);
493 FW_ASSERT(previousState == OWNED, static_cast<FwAssertArgType>(previousState));
496 this->m_state = WAITING;
502 if (this->getQueueDepth(index) == 0) {
514 status = queue.
dequeue(comBuffer);
519 status = queue.
dequeue(buffer);
525 void ComQueue::processQueue() {
533 for (priorityIndex = 0; priorityIndex <
TOTAL_PORT_COUNT; priorityIndex++) {
534 QueueMetadata& entry = this->m_prioritizedList[priorityIndex];
538 if ((entry.depth == 0) || (queue.
getQueueSize() == 0)) {
545 FW_ASSERT(this->m_buffer_state.load() == OWNED);
546 auto dequeue_status = queue.
dequeue(this->m_dequeued_com_buffer);
548 static_cast<FwAssertArgType>(dequeue_status));
549 this->sendComBuffer(this->m_dequeued_com_buffer, entry.index);
552 auto dequeue_status = queue.
dequeue(buffer);
554 static_cast<FwAssertArgType>(dequeue_status));
555 this->sendBuffer(buffer, entry.index);
559 this->m_throttle[entry.index] =
false;
562 sendPriority = entry.priority;
569 for (priorityIndex++;
570 priorityIndex <
TOTAL_PORT_COUNT && (this->m_prioritizedList[priorityIndex].priority == sendPriority);
573 QueueMetadata temp = this->m_prioritizedList[priorityIndex];
574 this->m_prioritizedList[priorityIndex] = this->m_prioritizedList[priorityIndex - 1];
575 this->m_prioritizedList[priorityIndex - 1] = temp;
582 if (portNum < 0 || portNum >= portCount) {
591 if (this->m_prioritizedList[i].index == queueNum) {
592 return this->m_prioritizedList[i].depth;
596 FW_ASSERT(
false, static_cast<FwAssertArgType>(queueNum));
Serialization/Deserialization operation was successful.
void cmdResponse_out(FwOpcodeType opCode, U32 cmdSeq, Fw::CmdResponse response)
Emit command response.
U16 FwPacketDescriptorType
The width of packet descriptors when they are serialized by the framework.
virtual void * allocate(const FwEnumStoreType identifier, FwSizeType &size, bool &recoverable, FwSizeType alignment=alignof(std::max_align_t))=0
void dataOut_out(FwIndexType portNum, Fw::Buffer &data, const ComCfg::FrameContext &context) const
Invoke output port dataOut.
FwIdType FwOpcodeType
The type of a command opcode.
std::make_unsigned< FwIndexType >::type FwUnsignedIndexType
PlatformSizeType FwSizeType
void tlmWrite_buffQueueDepth(const Svc::BuffQueueDepth &arg, Fw::Time _tlmTime=Fw::Time()) const
void configure(const QueueConfigurationTable &queueConfig, FwEnumStoreType allocationId, Fw::MemAllocator &allocator)
Serialization succeeded, but deleted old data.
QueueConfigurationEntry entries[TOTAL_PORT_COUNT]
configuration table for each queue
static const FwIndexType TOTAL_PORT_COUNT
Total count of input buffer ports and thus total queues.
ComQueue(const char *const compName)
Serializable::SizeType getSize() const override
Get current buffer size.
SerializeStatus deserializeTo(U8 &val, Endianness mode=Endianness::BIG) override
Deserialize an 8-bit unsigned integer value.
void setup(U8 *const storage, const FwSizeType storage_size, const FwSizeType depth, const FwSizeType message_size, const QueueMode mode=QUEUE_FIFO, const QueueOverflowMode overflow_mode=QUEUE_DROP_NEWEST)
setup the queue object to setup storage
No room left in the buffer to serialize data.
void set_apid(ComCfg::Apid::T apid)
Set member apid.
void log_ACTIVITY_HI_QueuePriorityChanged(const Svc::QueueType &queueType, FwIndexType indexType, FwIndexType newPriority) const
void clear_high_water_mark()
static const FwIndexType BUFFER_PORT_COUNT
static const FwIndexType COM_PORT_COUNT
< Count of Fw::Com input ports and thus Fw::Com queues
An enumeration of queue data types.
FwIndexType get_comQueueIndex() const
Get member comQueueIndex.
void tlmWrite_comManagedDropped(const Svc::ComQueueManagedDrops &arg, Fw::Time _tlmTime=Fw::Time())
SerializeStatus
forward declaration for string
ExternalSerializeBufferWithMemberCopy getDeserializer()
void log_WARNING_HI_QueueOverflow(const Svc::QueueType &queueType, FwIndexType index) const
FwIndexType priority
Priority of the queue [0, TOTAL_PORT_COUNT)
Fw::SerializeStatus enqueue(const U8 *const message, const FwSizeType size)
pushes a fixed-size message onto the queue
void tlmWrite_buffManagedDropped(const Svc::BuffQueueManagedDrops &arg, Fw::Time _tlmTime=Fw::Time())
U8 * getBuffAddr()
Get buffer address for data filling (non-const version)
FwSizeType depth
Depth of the queue [0, infinity)
void bufferReturnOut_out(FwIndexType portNum, Fw::Buffer &fwBuffer) const
Invoke output port bufferReturnOut.
Command successfully executed.
void tlmWrite_comIngressDropped(const Svc::ComQueueIngressDrops &arg, Fw::Time _tlmTime=Fw::Time())
Memory Allocation base class.
void set_comQueueIndex(FwIndexType comQueueIndex)
Set member comQueueIndex.
Types::QueueOverflowMode overflowMode
Overflow handling mode (DROP_NEWEST or DROP_OLDEST)
First-In-First-Out: dequeue from front.
enum T e
The raw enum value.
FwSizeType get_high_water_mark() const
Size of Fw::Buffer when serialized.
PlatformIndexType FwIndexType
Drop the newest (incoming) message on overflow.
FwSizeType SizeType
The size type for a buffer - for backwards compatibility.
Types::QueueMode mode
Queue mode (FIFO or LIFO)
C++ header for working with basic fprime types.
#define FW_NUM_ARRAY_ELEMENTS(a)
number of elements in an array
Type used to pass context info between components during framing/deframing.
void tlmWrite_buffIngressDropped(const Svc::BuffQueueIngressDrops &arg, Fw::Time _tlmTime=Fw::Time())
bool isConnected_bufferReturnOut_OutputPort(FwIndexType portNum) const
void tlmWrite_comQueueDepth(const Svc::ComQueueDepth &arg, Fw::Time _tlmTime=Fw::Time()) const
Command failed validation.
RateGroupDivider component implementation.
virtual void deallocate(const FwEnumStoreType identifier, void *ptr)=0
Drop the oldest (front) message on overflow.
size when serialized: buffer + stored size
Fw::SerializeStatus popFront(U8 *const message, const FwSizeType size)
removes and returns the oldest (front) message regardless of queue mode
FwSizeType getQueueSize() const
Fw::SerializeStatus dequeue(U8 *const message, const FwSizeType size)
pops a fixed-size message off the queue
void runInternal_internalInterfaceInvoke()
Internal interface base-class function for runInternal.
Auto-generated base for ComQueue component.