FreeRTOS之vTaskDelete实现分析

news2024/11/23 9:28:55

这里写自定义目录标题

  • 1 函数接口
    • 1.1 函数接口
    • 1.2 函数参数简介
  • 2 vTaskDelete的调用关系
    • 2.1 调用关系
    • 2.2 调用关系示意图
  • 3 函数源码分析
    • 3.1 vTaskDelete
    • 3.2 uxListRemove

1 函数接口

1.1 函数接口

void vTaskDelete( TaskHandle_t xTaskToDelete )

1.2 函数参数简介

  • TaskHandle_t xTaskToDelete 要删除任务的句柄,但这个句柄其实就是我们申请任务时创建的TCB,这个参数在传入的时候可以设置为NULL,表示要删除的是自己当前的任务。

2 vTaskDelete的调用关系

2.1 调用关系

|- vTaskDelete
	|- pxTCB = prvGetTCBFromHandle( xTaskToDelete );
	|- uxListRemove( &( pxTCB->xStateListItem ) )
	|- taskRESET_READY_PRIORITY( pxTCB->uxPriority );
	|- vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
	|- taskYIELD_WITHIN_API();

2.2 调用关系示意图

3 函数源码分析

3.1 vTaskDelete

  • pxTCB = prvGetTCBFromHandle( xTaskToDelete ); 获取要删除任务的TCB
  • uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 将当前要删除的任务从pxReadyTasksLists对应优先级的链表里面删除,并判断该优先级的任务数是不是为0了,如果当前该优先级的链表里已经没有任务则需要调用taskRESET_READY_PRIORITY( pxTCB->uxPriority );去做重置将该优先级在uxTopReadyPriority中mask掉。
  • vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) ); 如果当前的任务处于运行状态,则将当前要删除的任务放入到xTasksWaitingTermination列表,等到idle task执行的时候再去执行删除操作。任务是否处于调度状态的判断依据是xSchedulerRunning是否是pdTRUE,该状态位在执行vTaskStartScheduler函数时被置位,在执行vTaskEndScheduler函数时被置位pdFALSE,因此只要是当前的系统调度没有停就需要将要删除的任务的TCB加入到xTasksWaitingTermination链表中。
  • ++uxDeletedTasksWaitingCleanUp 记录等待清理任务的数量,在idle task或者vTaskEndScheduler执行时,以该全局变量作为清理数量的标准。
  • xDeleteTCBInIdleTask = pdTRUE; 标记当前任务要再idle task里面做删除工作。
  • taskYIELD_WITHIN_API();或者prvYieldCore( pxTCB->xTaskRunState ); 将处理器让出去,调度其他的任务。
void vTaskDelete( TaskHandle_t xTaskToDelete )
{
	TCB_t * pxTCB;
	BaseType_t xDeleteTCBInIdleTask = pdFALSE;
	BaseType_t xTaskIsRunningOrYielding;

	traceENTER_vTaskDelete( xTaskToDelete );

	taskENTER_CRITICAL();
	{
		获取当前要删除任务的TCB,如果xTaskToDelete 为空则表示要删除当前正在运行的任务,否则就找到对应任务的TCB。
		pxTCB = prvGetTCBFromHandle( xTaskToDelete );
		configASSERT( pxTCB != NULL );

		把当前要删除的任务从ready/delayed 链表中删除,并判断任务优先级的链表任务数是否为0
		if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
		{
			如果当前要删除的任务优先级所对应的链表任务数为0,则将该优先级在uxTopReadyPriority中mask掉。
			taskRESET_READY_PRIORITY( pxTCB->uxPriority );
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}

		判断当前的任务是否在一个event的链表,如果是则通过uxListRemove将其移除
		if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
		{
			( void ) uxListRemove( &( pxTCB->xEventListItem ) );
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}

		/* Increment the uxTaskNumber also so kernel aware debuggers can
		 * detect that the task lists need re-generating.  This is done before
		 * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
		 * not return. */
		uxTaskNumber++;

		通过taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD来判断当前的任务是否在运行状态,如果其xTaskRunState被设置为-1则表明其不处于运行状态,正常运行的任务其xTaskRunState值会被设置为所运行的core的id。
		xTaskIsRunningOrYielding = taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB );

		根据xSchedulerRunning 来判断当前的是否还处于正常的调度状态,该全局变量在vTaskStartScheduler函数被执行时设置为pdTRUE,在vTaskEndScheduler时被设置为pdFALSE
		if( ( xSchedulerRunning != pdFALSE ) && ( xTaskIsRunningOrYielding != pdFALSE ) )
		{
			为了防止该任务在其他core上还有运行的,所以将该任务添加到xTasksWaitingTermination链表上,等idle task运行时再做清理工作。
			vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );

			标记当前需要做清理的任务数
			++uxDeletedTasksWaitingCleanUp;

			/* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
			 * portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
			traceTASK_DELETE( pxTCB );

			用以标记有任务需要删除,如果需要设置为pdTRUE,则在后面会调用prvDeleteTCB( pxTCB );释放掉这块内存空间。
			xDeleteTCBInIdleTask = pdTRUE;

			/* The pre-delete hook is primarily for the Windows simulator,
			 * in which Windows specific clean up operations are performed,
			 * after which it is not possible to yield away from this task -
			 * hence xYieldPending is used to latch that a context switch is
			 * required. */
			#if ( configNUMBER_OF_CORES == 1 )
				portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ 0 ] ) );
			#else
				portPRE_TASK_DELETE_HOOK( pxTCB, &( xYieldPendings[ pxTCB->xTaskRunState ] ) );
			#endif

			在SMP系统给按任务让出CPU,让其他任务去运行
			#if ( configNUMBER_OF_CORES > 1 )
			{
				if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE )
				{
					if( pxTCB->xTaskRunState == ( BaseType_t ) portGET_CORE_ID() )
					{
						configASSERT( uxSchedulerSuspended == 0 );
						taskYIELD_WITHIN_API();
					}
					else
					{
						prvYieldCore( pxTCB->xTaskRunState );
					}
				}
			}
			#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
		}
		else
		{
			--uxCurrentNumberOfTasks;
			traceTASK_DELETE( pxTCB );

			/* Reset the next expected unblock time in case it referred to
			 * the task that has just been deleted. */
			prvResetNextTaskUnblockTime();
		}
	}
	taskEXIT_CRITICAL();

	/* If the task is not deleting itself, call prvDeleteTCB from outside of
	 * critical section. If a task deletes itself, prvDeleteTCB is called
	 * from prvCheckTasksWaitingTermination which is called from Idle task. */
	if( xDeleteTCBInIdleTask != pdTRUE )
	{
		prvDeleteTCB( pxTCB );
	}

	/* Force a reschedule if it is the currently running task that has just
	 * been deleted. */
	#if ( configNUMBER_OF_CORES == 1 )
	{
		if( xSchedulerRunning != pdFALSE )
		{
			if( pxTCB == pxCurrentTCB )
			{
				configASSERT( uxSchedulerSuspended == 0 );
				taskYIELD_WITHIN_API();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
	}
	#endif /* #if ( configNUMBER_OF_CORES == 1 ) */

	traceRETURN_vTaskDelete();
}

3.2 uxListRemove

  • pxList = pxItemToRemove->pxContainer; 通过pxContainer找到当前任务优先级所对应链表的链表头
  • pxList->uxNumberOfItems 返回当前任务优先级链表还剩余的任务数,一般用于判断链表所挂任务是否为0,用以来确定当前任务的优先级是否需要mask掉。
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{
    /* The list item knows which list it is in.  Obtain the list from the list
     * item. */
    List_t * const pxList = pxItemToRemove->pxContainer;

    traceENTER_uxListRemove( pxItemToRemove );

    pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
    pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

    /* Only used during decision coverage testing. */
    mtCOVERAGE_TEST_DELAY();

    /* Make sure the index is left pointing to a valid item. */
    if( pxList->pxIndex == pxItemToRemove )
    {
        pxList->pxIndex = pxItemToRemove->pxPrevious;
    }
    else
    {
        mtCOVERAGE_TEST_MARKER();
    }

    pxItemToRemove->pxContainer = NULL;
    ( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems - 1U );

    traceRETURN_uxListRemove( pxList->uxNumberOfItems );

    return pxList->uxNumberOfItems;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2245900.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s集群加入node节点为ubuntu 22.04

文章目录 1.环境准备1.1 关闭无用服务1.2 环境和网络1.3 apt源1.4 系统优化 2. 装containerd3. 接入k8s集群3.1 kubelet、kubeadm、kubectl安装3.2 缺少一个镜像3.3 接入k8s集群 4. 一些相关问题 1.环境准备 rootcto-gpu-pro-n01:~# lsb_release -a No LSB modules are availa…

低速接口项目之串口Uart开发(七)——如何在FPGA项目中实现自适应波特率串口功能

本节目录 一、自适应波特率串口 二、自适应波特率串口设计思路 三、自适应波特率串口测试验证 四、往期文章链接本节内容 一、自适应波特率串口 串口波特率Baud,具体定义此处不再进行描述,常用的波特率数值有115200、57600、38400、19200、9600等,FPG…

JS中的正则表达式简要梳理

文章目录 一、结构1、匹配模式2、字符组3、量词4、贪婪匹配和惰性匹配5、多选分支6、匹配模式关键词 二、位置1、位置锚点 三、括号分组1、分组2、分支结构3、引用分组4、括号嵌套 四、回溯模式1、回溯匹配 正则表达式(Regular Expression)‌是一种强大的…

【风水】-- 买车和用车的风水知识

目录 一、阴阳与车的风水 1. 车的属性:阴阳平衡 2. 车主与车的阴阳互补 二、五行与车的风水 1. 车的颜色与五行 2. 车主的五行与车的五行匹配 3. 五行相生相克的应用 三、八卦与车的风水 1. 车位选择与八卦方位 2. 车内布置与八卦 四、总结 结合阴阳、五…

深度剖析Linux进程控制

文章目录 🍕前言🥝进程创建fork 函数fork函数返回值写时拷贝fork 使用场景fork调用失败的原因 🥥进程终止进程退出码进程正常退出return 退出exit 函数_exit 函数return VS exit VS _exit 进程异常退出 🍇进程等待进程等待的必要性…

网络安全,文明上网(6)网安相关法律

列举 1. 《中华人民共和国网络安全法》: - 这是中国网络安全的基本法律,于2017年6月1日开始实施。该法律明确了网络运营者的安全保护义务,包括采取数据分类、重要数据备份和加密等措施。 2. 《中华人民共和国数据安全法》: …

IDEA2023 SpringBoot整合MyBatis(三)

一、数据库表 CREATE TABLE students (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,age INT,gender ENUM(Male, Female, Other),email VARCHAR(100) UNIQUE,phone_number VARCHAR(20),address VARCHAR(255),date_of_birth DATE,enrollment_date DATE,cours…

【Vue】 npm install amap-js-api-loader指南

前言 项目中的地图模块突然打不开了 正文 版本太低了,而且Vue项目就应该正经走项目流程啊喂! npm i amap/amap-jsapi-loader --save 官方说这样执行完,就这结束啦!它结束了,我还没有,不然不可能记录这篇文…

八股文:适合背诵的基础知识进行整理

四、IO进程:IPC 1. 标准IO和系统IO的区别 标准文件IO 概念:C库中定义的一组用于输入输出的函数 特点 (1)有缓存机制,减少系统调用 (2)围绕文件流进行操作 (3)默认…

面试干货:软件测试常见面试题(附答案)

1、文档测试主要包含什么内容? 参考答案: 在国内软件开发管理中,文档管理几乎是最弱的一项,因而在测试工作中特别容易忽略文档测试也就不足为奇了。要想给用户提供完整的产品,文档测试是必不可少的。文档测试一般注重下面几个方…

查询 linux相关信息

文章目录 前言查询 linux相关信息1. 查询内存大小(mem)2. 统计 当前系统的 CPU 核心数3. 查看系统的操作系统信息4. Ubuntu 系统版本的版本号 前言 如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊&#xff…

【动手学深度学习Pytorch】4. 神经网络基础

模型构造 回顾一下感知机。 nn.Sequential():定义了一种特殊的module。 torch.rand():用于生成具有均匀分布的随机数,这些随机数的范围在[0, 1)之间。它接受一个形状参数(shape),返回一个指定形状的张量&am…

新版自助笔记-工作记录-2024-11-18

环境&#xff1a; Windows11 .Net 4.5.2 Vs20151.Web <sKey>平台上获取的通讯码</sKey> Web -> 设置 -> 系统设置 -> 通讯密钥<SoftKey>设备身份识别码</SoftKey> Web -> 终端设备管理 -> 身份识别码<ZZUrl>Web服务</ZZUr…

【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux课程学习 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ ​ 目录 替换原理&#xff1a; 替换函数&…

Bug:引入Feign后触发了2次、4次ContextRefreshedEvent

Bug&#xff1a;引入Feign后发现监控onApplication中ContextRefreshedEvent事件触发了2次或者4次。 【原理】在Spring的文档注释中提示到&#xff1a; Event raised when an {code ApplicationContext} gets initialized or refreshed.即当 ApplicationContext 进行初始化或者刷…

【智谱清言-注册_登录安全分析报告】

前言 由于网站注册入口容易被机器执行自动化程序攻击&#xff0c;存在如下风险&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露&#xff0c;不符合国家等级保护的要求。短信盗刷带来的拒绝服务风险 &#xff0c;造成用户无法登陆、注册&#xff0c;大量收到垃圾短信的…

煤炉Mercari新手开店十问十答

在跨境电商的浪潮中&#xff0c;Mercari&#xff08;煤炉&#xff09;作为一个备受瞩目的C2C二手商品交易平台&#xff0c;吸引了众多新手卖家的目光。然而&#xff0c;初次在Mercari开店可能会遇到各种问题和挑战。为此&#xff0c;我特别整理了2024年最新的十问十答指南&…

[面试]-golang基础面试题总结

文章目录 panic 和 recover**注意事项**使用 pprof、trace 和 race 进行性能调试。**Go Module**&#xff1a;Go中new和make的区别 Channel什么是 Channel 的方向性&#xff1f;如何对 Channel 进行方向限制&#xff1f;Channel 的缓冲区大小对于 Channel 和 Goroutine 的通信有…

【Flask+Gunicorn+Nginx】部署目标检测模型API完整解决方案

【Ubuntu 22.04FlaskGunicornNginx】部署目标检测模型API完整解决方案 文章目录 1. 搭建深度学习环境1.1 下载Anaconda1.2 打包环境1.3 创建虚拟环境1.4 报错 2. 安装flask3. 安装gunicorn4. 安装Nginx4.1 安装前置依赖4.2 安装nginx4.3 常用命令 5. NginxGunicornFlask5.1 ng…

一个用纯PHP开发的服务器-workerman

什么是Workerman 简单的说Workerman是一个纯php开发的服务器。 workerman的目标是让PHP开发者更容易的开发出基于socket的高性能的应用服务&#xff0c;而不用去了解PHP socket以及PHP多进程细节。 workerman本身是一个PHP多进程服务器&#xff0c;类似nginxphp-fpm的结合体&am…