2022-04-19 19:18:37 -04:00
|
|
|
/*============================================================================
|
|
|
|
* QP/C Real-Time Embedded Framework (RTEF)
|
|
|
|
* Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
2022-04-19 19:18:37 -04:00
|
|
|
* SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
2022-04-19 19:18:37 -04:00
|
|
|
* This software is dual-licensed under the terms of the open source GNU
|
|
|
|
* General Public License version 3 (or any later version), or alternatively,
|
|
|
|
* under the terms of one of the closed source Quantum Leaps commercial
|
|
|
|
* licenses.
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
2022-04-19 19:18:37 -04:00
|
|
|
* The terms of the open source GNU General Public License version 3
|
|
|
|
* can be found at: <www.gnu.org/licenses/gpl-3.0>
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
2022-04-19 19:18:37 -04:00
|
|
|
* The terms of the closed source Quantum Leaps commercial licenses
|
|
|
|
* can be found at: <www.state-machine.com/licensing>
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
2022-04-19 19:18:37 -04:00
|
|
|
* Redistributions in source code must retain this top-level comment block.
|
|
|
|
* Plagiarizing this software to sidestep the license obligations is illegal.
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
|
|
|
* Contact information:
|
2022-04-19 19:18:37 -04:00
|
|
|
* <www.state-machine.com>
|
2019-10-27 11:57:33 -04:00
|
|
|
* <info@state-machine.com>
|
2022-04-19 19:18:37 -04:00
|
|
|
============================================================================*/
|
|
|
|
/*!
|
|
|
|
* @date Last updated on: 2021-12-23
|
|
|
|
* @version Last updated for: @ref qpc_7_0_0
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief QP natvie, platform-independent, thread-safe event queue interface
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2012-08-14 18:07:04 -04:00
|
|
|
* This header file must be included in all QF ports that use native QF
|
2014-04-06 11:43:13 -04:00
|
|
|
* event queue for active objects. Also, this file needs to be included
|
|
|
|
* in the QP/C library when the application uses QActive_defer()/
|
|
|
|
* QActive_recall(). Finally, this file is also needed when the "raw"
|
2012-08-14 18:07:04 -04:00
|
|
|
* thread-safe queues are used for communication between active objects
|
|
|
|
* and non-framework entities, such as ISRs, device drivers, or legacy
|
|
|
|
* code.
|
2022-04-19 19:18:37 -04:00
|
|
|
* @ingroup qf
|
2012-08-14 18:07:04 -04:00
|
|
|
*/
|
2022-04-19 19:18:37 -04:00
|
|
|
#ifndef QEQUEUE_H
|
|
|
|
#define QEQUEUE_H
|
2012-08-14 18:07:04 -04:00
|
|
|
|
|
|
|
#ifndef QF_EQUEUE_CTR_SIZE
|
|
|
|
|
2020-03-17 21:33:20 -04:00
|
|
|
/*! The size [bytes] of the ring-buffer counters used in the
|
|
|
|
* native QF event queue implementation. Valid values: 1U, 2U, or 4U;
|
2022-04-19 19:18:37 -04:00
|
|
|
* default 1U.
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2012-08-14 18:07:04 -04:00
|
|
|
* This macro can be defined in the QF port file (qf_port.h) to
|
|
|
|
* configure the ::QEQueueCtr type. Here the macro is not defined so the
|
|
|
|
* default of 1 byte is chosen.
|
|
|
|
*/
|
2020-03-17 21:33:20 -04:00
|
|
|
#define QF_EQUEUE_CTR_SIZE 1U
|
2012-08-14 18:07:04 -04:00
|
|
|
#endif
|
2020-03-17 21:33:20 -04:00
|
|
|
#if (QF_EQUEUE_CTR_SIZE == 1U)
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/*! The data type to store the ring-buffer counters based on
|
2022-04-19 19:18:37 -04:00
|
|
|
* the macro #QF_EQUEUE_CTR_SIZE.
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2012-08-14 18:07:04 -04:00
|
|
|
* The dynamic range of this data type determines the maximum length
|
|
|
|
* of the ring buffer managed by the native QF event queue.
|
|
|
|
*/
|
2017-12-11 12:13:22 -05:00
|
|
|
typedef uint8_t QEQueueCtr;
|
2020-03-17 21:33:20 -04:00
|
|
|
#elif (QF_EQUEUE_CTR_SIZE == 2U)
|
2017-12-11 12:13:22 -05:00
|
|
|
typedef uint16_t QEQueueCtr;
|
2020-03-17 21:33:20 -04:00
|
|
|
#elif (QF_EQUEUE_CTR_SIZE == 4U)
|
2017-12-11 12:13:22 -05:00
|
|
|
typedef uint32_t QEQueueCtr;
|
2012-08-14 18:07:04 -04:00
|
|
|
#else
|
2020-03-17 21:33:20 -04:00
|
|
|
#error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U"
|
2012-08-14 18:07:04 -04:00
|
|
|
#endif
|
|
|
|
|
2022-04-19 19:18:37 -04:00
|
|
|
/*==========================================================================*/
|
|
|
|
|
|
|
|
/*! Native QF Event Queue
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2014-04-06 11:43:13 -04:00
|
|
|
* This class describes the native QF event queue, which can be used as
|
2012-08-14 18:07:04 -04:00
|
|
|
* the event queue for active objects, or as a simple "raw" event queue for
|
|
|
|
* thread-safe event passing among non-framework entities, such as ISRs,
|
2015-04-28 13:45:35 -04:00
|
|
|
* device drivers, or other third-party components.@n
|
|
|
|
* @n
|
2012-08-14 18:07:04 -04:00
|
|
|
* The native QF event queue is configured by defining the macro
|
2015-04-28 13:45:35 -04:00
|
|
|
* #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file.@n
|
|
|
|
* @n
|
2012-08-14 18:07:04 -04:00
|
|
|
* The ::QEQueue structure contains only data members for managing an event
|
|
|
|
* queue, but does not contain the storage for the queue buffer, which must
|
2015-04-28 13:45:35 -04:00
|
|
|
* be provided externally during the queue initialization.@n
|
|
|
|
* @n
|
2012-08-14 18:07:04 -04:00
|
|
|
* The event queue can store only event pointers, not the whole events. The
|
|
|
|
* internal implementation uses the standard ring-buffer plus one external
|
|
|
|
* location that optimizes the queue operation for the most frequent case
|
2015-04-28 13:45:35 -04:00
|
|
|
* of empty queue.@n
|
|
|
|
* @n
|
2012-08-14 18:07:04 -04:00
|
|
|
* The ::QEQueue structure is used with two sets of functions. One set is for
|
2014-04-06 11:43:13 -04:00
|
|
|
* the active object event queue, which might need to block the active object
|
|
|
|
* task when the event queue is empty and might need to unblock it when
|
|
|
|
* events are posted to the queue. The interface for the native active object
|
|
|
|
* event queue consists of the following functions: QActive_post(),
|
|
|
|
* QActive_postLIFO(), and QActive_get_(). Additionally the function
|
2015-04-28 13:45:35 -04:00
|
|
|
* QEQueue_init() is used to initialize the queue.@n
|
|
|
|
* @n
|
2014-04-06 11:43:13 -04:00
|
|
|
* The other set of functions, uses ::QEQueue as a simple "raw" event
|
2012-08-14 18:07:04 -04:00
|
|
|
* queue to pass events between entities other than active objects, such as
|
|
|
|
* ISRs. The "raw" event queue is not capable of blocking on the get()
|
|
|
|
* operation, but is still thread-safe because it uses QF critical section
|
|
|
|
* to protect its integrity. The interface for the "raw" thread-safe queue
|
2013-09-23 14:34:35 -04:00
|
|
|
* consists of the following functions: QEQueue_post(),
|
2012-08-14 18:07:04 -04:00
|
|
|
* QEQueue_postLIFO(), and QEQueue_get(). Additionally the function
|
|
|
|
* QEQueue_init() is used to initialize the queue.
|
|
|
|
*
|
2015-04-28 13:45:35 -04:00
|
|
|
* @note Most event queue operations (both the active object queues and
|
2012-08-14 18:07:04 -04:00
|
|
|
* the "raw" queues) internally use the QF critical section. You should be
|
|
|
|
* careful not to invoke those operations from other critical sections when
|
|
|
|
* nesting of critical sections is not supported.
|
|
|
|
*
|
2015-04-28 13:45:35 -04:00
|
|
|
* @sa ::QEQueue for the description of the data members
|
2012-08-14 18:07:04 -04:00
|
|
|
*/
|
2014-04-06 11:43:13 -04:00
|
|
|
typedef struct QEQueue {
|
2022-04-19 19:18:37 -04:00
|
|
|
/*! pointer to event at the front of the queue.
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2012-08-14 18:07:04 -04:00
|
|
|
* All incoming and outgoing events pass through the frontEvt location.
|
|
|
|
* When the queue is empty (which is most of the time), the extra
|
|
|
|
* frontEvt location allows to bypass the ring buffer altogether,
|
|
|
|
* greatly optimizing the performance of the queue. Only bursts of events
|
|
|
|
* engage the ring buffer.
|
|
|
|
*
|
2015-04-28 13:45:35 -04:00
|
|
|
* @note The additional role of this attribute is to indicate the empty
|
2014-04-06 11:43:13 -04:00
|
|
|
* status of the queue. The queue is empty when frontEvt is NULL.
|
2012-08-14 18:07:04 -04:00
|
|
|
*/
|
2013-09-23 14:34:35 -04:00
|
|
|
QEvt const * volatile frontEvt;
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-13 21:30:44 -04:00
|
|
|
/*! pointer to the start of the ring buffer. */
|
2012-08-14 18:07:04 -04:00
|
|
|
QEvt const **ring;
|
|
|
|
|
2014-04-13 21:30:44 -04:00
|
|
|
/*! offset of the end of the ring buffer from the start of the buffer. */
|
2012-08-14 18:07:04 -04:00
|
|
|
QEQueueCtr end;
|
|
|
|
|
2014-04-13 21:30:44 -04:00
|
|
|
/*! offset to where next event will be inserted into the buffer. */
|
2013-09-23 14:34:35 -04:00
|
|
|
QEQueueCtr volatile head;
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-13 21:30:44 -04:00
|
|
|
/*! offset of where next event will be extracted from the buffer. */
|
2013-09-23 14:34:35 -04:00
|
|
|
QEQueueCtr volatile tail;
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-13 21:30:44 -04:00
|
|
|
/*! number of free events in the ring buffer. */
|
2013-09-23 14:34:35 -04:00
|
|
|
QEQueueCtr volatile nFree;
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2022-04-19 19:18:37 -04:00
|
|
|
/*! minimum number of free events ever in the ring buffer.
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2014-04-06 11:43:13 -04:00
|
|
|
* this attribute remembers the low-watermark of the ring buffer,
|
2012-08-14 18:07:04 -04:00
|
|
|
* which provides a valuable information for sizing event queues.
|
2015-04-28 13:45:35 -04:00
|
|
|
* @sa QF_getQueueMargin().
|
2012-08-14 18:07:04 -04:00
|
|
|
*/
|
|
|
|
QEQueueCtr nMin;
|
|
|
|
} QEQueue;
|
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/* public class operations */
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/*! Initialize the native QF event queue */
|
2012-08-14 18:07:04 -04:00
|
|
|
void QEQueue_init(QEQueue * const me,
|
2020-03-17 21:33:20 -04:00
|
|
|
QEvt const * * const qSto, uint_fast16_t const qLen);
|
2013-09-23 14:34:35 -04:00
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/*! Post an event to the "raw" thread-safe event queue (FIFO). */
|
|
|
|
bool QEQueue_post(QEQueue * const me, QEvt const * const e,
|
2020-10-01 12:48:48 -04:00
|
|
|
uint_fast16_t const margin, uint_fast8_t const qs_id);
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/*! Post an event to the "raw" thread-safe event queue (LIFO). */
|
2020-10-01 12:48:48 -04:00
|
|
|
void QEQueue_postLIFO(QEQueue * const me, QEvt const * const e,
|
|
|
|
uint_fast8_t const qs_id);
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/*! Obtain an event from the "raw" thread-safe queue. */
|
2020-10-01 12:48:48 -04:00
|
|
|
QEvt const *QEQueue_get(QEQueue * const me, uint_fast8_t const qs_id);
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/*! "raw" thread-safe QF event queue operation for obtaining the number
|
2022-04-19 19:18:37 -04:00
|
|
|
* of free entries still available in the queue.
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2014-04-06 11:43:13 -04:00
|
|
|
* This operation needs to be used with caution because the number of free
|
|
|
|
* entries can change unexpectedly. The main intent for using this operation
|
|
|
|
* is in conjunction with event deferral. In this case the queue is accessed
|
|
|
|
* only from a single thread (by a single AO), so the number of free
|
|
|
|
* entries cannot change unexpectedly.
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
2022-04-19 19:18:37 -04:00
|
|
|
* @param[in] me pointer (see @ref oop)
|
2012-08-14 18:07:04 -04:00
|
|
|
*
|
2015-04-28 13:45:35 -04:00
|
|
|
* @returns the current number of free slots in the queue.
|
2012-08-14 18:07:04 -04:00
|
|
|
*/
|
2022-04-19 19:18:37 -04:00
|
|
|
static inline QEQueueCtr QEQueue_getNFree(QEQueue * const me) {
|
|
|
|
return me->nFree;
|
|
|
|
}
|
2012-08-14 18:07:04 -04:00
|
|
|
|
2015-04-28 13:45:35 -04:00
|
|
|
/*! "raw" thread-safe QF event queue operation for obtaining the minimum
|
2022-04-19 19:18:37 -04:00
|
|
|
* number of free entries ever in the queue (a.k.a. "low-watermark").
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
|
|
|
* This operation needs to be used with caution because the "low-watermark"
|
|
|
|
* can change unexpectedly. The main intent for using this operation is to
|
|
|
|
* get an idea of queue usage to size the queue adequately.
|
|
|
|
*
|
2022-04-19 19:18:37 -04:00
|
|
|
* @param[in] me pointer (see @ref oop)
|
2015-04-28 13:45:35 -04:00
|
|
|
*
|
|
|
|
* @returns the minimum number of free entries ever in the queue since init.
|
|
|
|
*/
|
2022-04-19 19:18:37 -04:00
|
|
|
static inline QEQueueCtr QEQueue_getNMin(QEQueue * const me) {
|
|
|
|
return me->nMin;
|
|
|
|
}
|
2015-04-28 13:45:35 -04:00
|
|
|
|
2014-04-06 11:43:13 -04:00
|
|
|
/*! "raw" thread-safe QF event queue operation to find out if the queue
|
2022-04-19 19:18:37 -04:00
|
|
|
* is empty.
|
2015-04-28 13:45:35 -04:00
|
|
|
* @description
|
2014-04-06 11:43:13 -04:00
|
|
|
* This operation needs to be used with caution because the queue status
|
|
|
|
* can change unexpectedly. The main intent for using this operation is in
|
|
|
|
* conjunction with event deferral. In this case the queue is accessed only
|
|
|
|
* from a single thread (by a single AO), so no other entity can post
|
|
|
|
* events to the queue.
|
2012-12-10 16:00:27 -05:00
|
|
|
*
|
2015-04-28 13:45:35 -04:00
|
|
|
* @param[in] me_ pointer (see @ref oop)
|
2012-12-10 16:00:27 -05:00
|
|
|
*
|
2015-04-28 13:45:35 -04:00
|
|
|
* @returns 'true' if the queue is current empty and 'false' otherwise.
|
2012-12-10 16:00:27 -05:00
|
|
|
*/
|
2022-04-19 19:18:37 -04:00
|
|
|
static inline bool QEQueue_isEmpty(QEQueue * const me) {
|
|
|
|
return me->frontEvt == (QEvt *)0;
|
|
|
|
}
|
2012-12-10 16:00:27 -05:00
|
|
|
|
2019-10-27 11:57:33 -04:00
|
|
|
#endif /* QEQUEUE_H */
|