FreeRTOS消息队列详解第四讲(全网最全)——队列上锁解锁

一、队列上锁

在任务级通用入队函数和中断级通用入队函数的时候都提到了队列的上锁和解锁,队列的上锁API函数为prvLockQueue()。首先来看一下队列上锁函数prvLockQueue(),此函数本质上就是一个宏,定义如下:

#define prvLockQueue( pxQueue )								\
	taskENTER_CRITICAL();									\
	{														\
		if( ( pxQueue )->cRxLock == queueUNLOCKED )			\
		{													\
			( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED;	\
		}													\
		if( ( pxQueue )->cTxLock == queueUNLOCKED )			\
		{													\
			( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED;	\
		}													\
	}														\
	taskEXIT_CRITICAL()

prvLockQueue()函数很简单,就是将队列中的成员变量cRxLock和cTxLock设置为queueLOCKED_UNMODIFIED就行了。

二、队列解锁

再来看一下队列的解锁函数prvUnlockQueue(),函数如下:

static void prvUnlockQueue( Queue_t * const pxQueue )
{
	/*上锁计数器(cTxLock和cRxLock)记录了在队列上锁期间,入队或出队的数量,当队列上锁以后队列项是可以加入或者移除队列的,但是对应的列表不会更新。*/
	taskENTER_CRITICAL();
	{
	//处理cTxLock
		int8_t cTxLock = pxQueue->cTxLock;
		while( cTxLock > queueLOCKED_UNMODIFIED )(1)
		{
//将任务从事件列表中移除
					if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )(2)
					{
						if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )(3)
						{
/*从列表中移除的任务优先级比当前任务优先级高,进行任务切换 */
							vTaskMissedYield();(4)
						}
						else
						{
							mtCOVERAGE_TEST_MARKER();
						}
					}
					else
					{
						break;
					}
				}
			}
			--cTxLock;(5)
		}

		pxQueue->cTxLock = queueUNLOCKED;(6)
	}
	taskEXIT_CRITICAL();

	/* Do the same for the Rx lock. */
	taskENTER_CRITICAL();
	{
	//处理cRxLock
		int8_t cRxLock = pxQueue->cRxLock;

		while( cRxLock > queueLOCKED_UNMODIFIED )(7)
		{
			if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
			{
				if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
				{
					vTaskMissedYield();
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}

				--cRxLock;
			}
			else
			{
				break;
			}
		}

		pxQueue->cRxLock = queueUNLOCKED;
	}
	taskEXIT_CRITICAL();
}
  • (1)、判断是否有中断向队列发送了消息。如果当队列上锁的话那么向队列发送消息成功以后会将入队计数器cTxLock加一。
  • (2)、判断列表xTasksWaitingToReceive是否为空,如果不为空的话就要将相应的任务从列表中移除。
  • (3)、将任务从列表xTasksWaitingToReceive中移除。
  • (4)、如果刚刚从列表xTasksWaitingToReceive中移除的任务优先级比当前任务的优先级高,那么就要标记需要进行任务切换。这里调用函数vTaskMissedYield(来完成此任务,函数vTaskMissedYield()只是简单的将全局变量xYieldPending设置为pdTRUE。在时钟节拍处理函数xTaskIncrementTick0中,此函数会判断xYieldPending的值,从而决定是否进行任务切换。
  • (5)、每处理完一条就将cTxLock减一,直到处理完所有的。
  • (6)、当处理完以后标记cTxLock为queueUNLOCKED,也就说cTxLock是没有上锁的了。
  • (7)、处理完cTxLock以后接下来就要处理xRxLock了,处理过程和xTxLock很类似。

队列上锁解锁就讲解到这里啦!!!

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

留小乙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值