[FreeRTOS 内部实现] 互斥量


基础知识

[FreeRTOS 基础知识] 互斥量 概念


创建互斥量

#define queueQUEUE_TYPE_MUTEX 				( ( uint8_t ) 1U )
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )

QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
	-> const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
	-> pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );		// 创建长度为1,大小为0的队列,作为互斥量
	-> prvInitialiseMutex( pxNewQueue );  // 初始化互斥量特殊参数
		-> pxNewQueue->pxMutexHolder = NULL;	// 互斥量持有者
		-> pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;	// 队列类型为互斥量
		-> pxNewQueue->u.uxRecursiveCallCount = 0;		//递归互斥
		-> ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );	// 确保互斥量值为初始状态

根据上面的定义,可知创建互斥量本质就是创建队列。长度(第一个参数)为1,大小(第二个参数)为0
在这里插入图片描述


获取互斥量

通过队列获取互斥量 函数与获取信号量 的方式是一样的。可以参考:[FreeRTOS 内部实现] 信号量

#define xSemaphoreTake( xSemaphore, xBlockTime )        xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) )
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )
	-> taskENTER_CRITICAL();   // 关中断
	-> const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;    // 获取当前信号量值
	-> pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;    // 信号量-1
	-> 	if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )		// 如果该队列是互斥量并且获取到互斥量
			pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); 	// 记录当前互斥量持有者
	-> 	if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )	//如果该队列是互斥量并且没有获取到互斥量
			xInheritanceOccurred = xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );	// 任务优先级继承
				-> if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )	// 当前的任务优先级大于持有互斥量任务的优先级
						if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )	// 持有互斥量的任务是否在状态链表中
							if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )		// 从状态链表中移除
								taskRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority );	
								pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;	// 设置高优先级
								prvAddTaskToReadyList( pxMutexHolderTCB );		// 持有互斥量的任务添加到就绪列表中
	->  vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); 
	    // 1、当前的任务加入到队列的xTasksWaitingToReceive链表中;
        // 2、当前的任务从ReadyList移动到DelayList
           

释放互斥量

通过队列释放互斥量 函数与释放信号量 的方式是一样的。可以参考:[FreeRTOS 内部实现] 信号量

#define semGIVE_BLOCK_TIME                    ( ( TickType_t ) 0U )
#define xSemaphoreGive( xSemaphore )        xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
	-> taskENTER_CRITICAL();    // 关中断 portDISABLE_INTERRUPTS();
	-> xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
       // 不会写数据,但是会将 uxMessagesWaiting +1, 取消当前任务继承
       	-> 	if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
				xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );		// 取消继承
					-> if( pxTCB->uxPriority != pxTCB->uxBasePriority )		// 当前的优先级与之前备份的优先级不同	
							if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )	// 从StateList移除
							-> traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
							-> pxTCB->uxPriority = pxTCB->uxBasePriority;		// 恢复之前优先级
							-> 	listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); 	// 重置事件链表值
							-> prvAddTaskToReadyList( pxTCB );		
		-> --uxMessagesWaiting;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Bazinga bingo

您的鼓励就是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值