FreeRTOS任务管理

任务管理

注:本次引用的两个重要函数的源码来源是FreeRTOS_V9.0中源码

一、函数分析

任务挂起函数
#if ( INCLUDE_vTaskSuspend == 1 )

	void vTaskSuspend( TaskHandle_t xTaskToSuspend )
	{
	TCB_t *pxTCB;
        /*进入临界态*/
		taskENTER_CRITICAL();
		{
			/* 如果要挂起的任务的TCB返回值是NULL就说明,将要挂起的任务是正在运行的任务 */
			pxTCB = prvGetTCBFromHandle( xTaskToSuspend );

			traceTASK_SUSPEND( pxTCB );

			/*查找将要放入挂起态链表的任务,在不在就绪态链表或者延时链表中*/
			if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
			{
				taskRESET_READY_PRIORITY( pxTCB->uxPriority );
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}

			/*查看将要挂起的函数在不在等待事件 */
			if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
			{
                /*如果在等待事件,就将其从等待事件中移除*/
				( void ) uxListRemove( &( pxTCB->xEventListItem ) );
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
            /*将要挂起的任务放入挂起态链表的尾部*/
			vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
		}
        /*退出临界态*/
		taskEXIT_CRITICAL();
        
        /* 判断调度器是否在运行 */
		if( xSchedulerRunning != pdFALSE )
		{
			taskENTER_CRITICAL();
			{
                /*复位下一次解除阻塞的时间*/
				prvResetNextTaskUnblockTime();
			}
			taskEXIT_CRITICAL();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
        
        /*如果挂起的任务是当前在运行的任务*/
		if( pxTCB == pxCurrentTCB )
		{
            /*当调度器在运行*/
			if( xSchedulerRunning != pdFALSE )
			{
				/* 刚刚被挂起 */
				configASSERT( uxSchedulerSuspended == 0 );
                /*请求发起一次任务调度*/
				portYIELD_WITHIN_API();
			}
			else
			{
				/* 如果调度器不运行,且所有任务都被挂起 */
				if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
				{
					/* 将TCB指针置空 */
					pxCurrentTCB = NULL;
				}
				else
				{
                    /*将TCB指针指向最高优先级的任务*/
					vTaskSwitchContext();
				}
			}
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}

#endif
任务恢复函数
#if ( INCLUDE_vTaskSuspend == 1 )

	void vTaskResume( TaskHandle_t xTaskToResume )
	{
	TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;

		/* 断言:如果任务不支持挂起,那释放也没有意义 */
		configASSERT( xTaskToResume );

		/* 参数为空表明恢复正在运行的任务,那是不可能的,那就没有了意义 */
		if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
		{
			taskENTER_CRITICAL();
			{
                /*如果任务是挂起的*/
				if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
				{
					traceTASK_RESUME( pxTCB );

					/* 将任务从挂起态链表中移除 */
					( void ) uxListRemove(  &( pxTCB->xStateListItem ) );
                    /*将任务加入到就绪态链表中*/
					prvAddTaskToReadyList( pxTCB );

					/* 如果恢复的任务是最高优先级的任务 */
					if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
					{
						/* 将任务放到下一个就可以运行的位置,并请求发起任务调度 */
						taskYIELD_IF_USING_PREEMPTION();
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			taskEXIT_CRITICAL();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}

#endif

二、运行机制

挂起任务

1.访问将要挂起的函数的任务句柄,去得到TCB来判断任务是不是正在执行。

2.如果任务不是正在执行,那么从就绪链表、延时链表中查找,找到后将其从其链表中移除。

3.如果没找到,就查看是不是在等待事件,如果是就从事件链表中移除。

4.以上就确保找到了任务所在位置,将其挂载到挂起态链表的尾部。

5.如果调度器在运行,复位下一次解除阻塞的时间。

6.如果是正在运行的任务,刚刚被挂起,就发起一次任务调度。

7.所有任务都不在运行,检测是否还有任务在等待运行,有就将TCB指针指向它,如果没有就将TCB指针置空。

恢复任务

1.将要恢复的任务是正在运行的任务,那是一件荒谬的事。

2.将将要恢复的任务从挂起态链表中移除。

3.将其添加到就绪态链表中。

4.如果恢复的任务是优先级最高的任务,就将其放入将要执行的位置,并申请发生一次任务调度。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值