[RTOS] queue structure based on RTOS source code

Posted by Grimloch on Thu, 04 Nov 2021 06:35:38 +0100

catalogue

preface

The following RTOS is based on FreeRTOS source code analysis.
It is recommended to look at the source code directly.

Li Zhuming's blog: https://www.cnblogs.com/lizhuming/p/15487239.html

IPC

I think one of the structures that must be understood when learning RTOS task communication is struct QueueDefinition. For its source code, please refer to the attachment - source code.
This structure is applied to message queue, binary semaphore, count semaphore, mutex, recursive mutex and other controls on inter task communication.

These controls in the system are composed of control block + storage area, and the structure is the role of control block to manage its corresponding storage area.

Member analysis

When analyzing members, it is analyzed by the function of message queue by default.

int8_t *pcHead;:

/* The starting position of the queue storage area corresponds to the first message space.*/
int8_t *pcHead;

int8_t *pcTail;:

/* The end of the message queue store.
 * The combined pcHead pointer is the legal area of the entire storage area.*/
int8_t *pcHead;

int8_t *pcWriteTo;:

/* Write pointer to the next free space in the storage area.
 * The position where the queue writes data next. Call this pointer to write data when you need to join the queue.*/
int8_t *pcWriteTo;

int8_t *pcReadFrom;:

/* Read pointer, pointing to the space of the next valid data in the storage area.
 * The location of the next data read by the queue. Call this pointer to write data when you need to leave the queue.*/
int8_t *pcReadFrom;

UBaseType_t uxRecursiveCallCount;:

/* Number of recursions.
 * Used when used for mutex. It is a union with pcReadFrom.
 * Record the number of times the recursive mutex was called. */
UBaseType_t uxRecursiveCallCount;

List_t xTasksWaitingToSend;:

/* List of tasks waiting to be sent.
 * When the queue storage area is full, the tasks that need to send messages are blocked and recorded in the linked list.
 * Sort by task priority. */
List_t xTasksWaitingToSend;

List_t xTasksWaitingToReceive;:

/* List of tasks waiting to be received.
 * When the queue storage area is empty, the task that needs to get the message is blocked and recorded in the linked list.
 * Sort by task priority. */
List_t xTasksWaitingToReceive;

volatile UBaseType_t uxMessagesWaiting;:

/* Number of current message nodes.
 * This is the current number of valid messages.
 * Binary semaphore and mutually exclusive semaphore: indicates whether a semaphore is available.
 * When counting semaphores: number of effective semaphores. */
volatile UBaseType_t uxMessagesWaiting;

UBaseType_t uxLength;:

/* The maximum number of nodes in the current queue.
 * That is, the maximum number of messages can be stored.
 * For binary semaphores and mutually exclusive semaphores: the maximum is 1.
 * When counting semaphores: the maximum number of semaphores. */
UBaseType_t uxLength;

UBaseType_t uxItemSize;:

/* The size of a single node.
 * The size of a single message.
 * Binary semaphore and mutually exclusive semaphore: 0.
 * When counting semaphores: 0. */
UBaseType_t uxItemSize;

volatile int8_t cRxLock;:

/* Record the number of data items of the team.
 * That is, how many blocked tasks in the receive wait list need to be unblocked. */
volatile int8_t cRxLock;

volatile int8_t cTxLock;:

/* Record the number of data items in the queue.
 * That is, how many tasks in the send waiting list need to be unblocked. */
volatile int8_t cTxLock;

cRxLock and cTxLock

When the service program is interrupted to operate the queue and the blocked task is unblocked.
First, judge whether the queue is locked:

  • If it is not locked, the blocked task will be released, and the context switching request flag will be set as required;
  • If the queue is locked, the blocked tasks will not be released. Instead, add xRxLock or xTxLock by 1, which indicates the number of outgoing or incoming tasks during queue locking, and also indicates that there are tasks that can be unblocked.

cRxLock corresponds to the number of people waiting to leave the team.
cTxLock corresponds to the number of people waiting to join the team.

Trigger unblock

Method of triggering unblocking:

  • Send and receive messages.

    • That is, when data items enter and leave the queue, the blocked task will be triggered to unblock.
  • Timeout.

    • Timeout will also trigger the corresponding blocking task to unblock.
  • Access to the team that is not handled when the lock is unlocked.

    • cRxLock and cTxLock.

Attachment - source code

/*
 * Definition of the queue used by the scheduler.
 * Items are queued by copy, not reference.  See the following link for the
 * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html
 */
typedef struct QueueDefinition
{
	int8_t *pcHead;					/*< Points to the beginning of the queue storage area. */
	int8_t *pcTail;					/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
	int8_t *pcWriteTo;				/*< Points to the free next place in the storage area. */

	union							/* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
	{
		int8_t *pcReadFrom;			/*< Points to the last place that a queued item was read from when the structure is used as a queue. */
		UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
	} u;

	List_t xTasksWaitingToSend;		/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
	List_t xTasksWaitingToReceive;	/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */

	volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */
	UBaseType_t uxLength;			/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
	UBaseType_t uxItemSize;			/*< The size of each items that the queue will hold. */

	volatile int8_t cRxLock;		/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
	volatile int8_t cTxLock;		/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */

	#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
		uint8_t ucStaticallyAllocated;	/*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */
	#endif

	#if ( configUSE_QUEUE_SETS == 1 )
		struct QueueDefinition *pxQueueSetContainer;
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t uxQueueNumber;
		uint8_t ucQueueType;
	#endif

} xQUEUE;

Topics: data structure Embedded system FreeRTOS