FreeRTOS之vTaskDelete实现分析

这里写自定义目录标题

  • 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 链表中删除,并判断任务优先级的链表任务数是否为0if( 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时被设置为pdFALSEif( ( 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 ] ) );#elseportPRE_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.mzph.cn/diannao/61571.shtml

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

相关文章

移动充储机器人“小奥”的多场景应用(上)

一、高速公路服务区应用 在高速公路服务区,新能源汽车的充电需求得到“小奥”机器人的及时响应。该机器人配备有储能电池和自动驾驶技术,能够迅速定位至指定充电点,为待充电的新能源汽车提供服务。得益于“小奥”的机动性,其服务…

Redis 的代理类注入失败,连不上 redis

在测试 redis 是否成功连接时&#xff0c;发现 bean 没有被创建成功&#xff0c;导致报错 根据报错提示&#xff0c;需要我们添加依赖&#xff1a; <dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>&l…

桌面怎么快速添加便签?适合桌面记事的便签小工具

在数字化时代&#xff0c;我们每天面对电脑处理大量任务&#xff0c;无论是工作计划、会议纪要还是个人生活琐事&#xff0c;都需要一个可靠的桌面记事工具来帮助我们记录和整理。因此&#xff0c;一款适合桌面使用的便签软件成为了我们不可或缺的助手。 敬业签就是这样一款功…

UE5 腿部IK 解决方案 footplacement

UE5系列文章目录 文章目录 UE5系列文章目录前言一、FootPlacement 是什么&#xff1f;二、具体实现 前言 在Unreal Engine 5 (UE5) 中&#xff0c;腿部IK&#xff08;Inverse Kinematics&#xff0c;逆向运动学&#xff09;是一个重要的动画技术&#xff0c;用于实现角色脚部准…

KLV6008固态继电器:高压应用的理想紧凑方案

在当今快节奏的电子领域&#xff0c;找到平衡性能、可靠性和安全性的组件至关重要。CRIA Semiconductor的KLV6008固态继电器(SSR)正是满足了这一要求。这款紧凑型继电器专为高压、低电流切换而设计&#xff0c;是适用于各种应用的多功能解决方案。 为什么选择KLV6008&#xff1…

在 Swift 中实现字符串分割问题:以字典中的单词构造句子

文章目录 前言摘要描述题解答案题解代码题解代码分析示例测试及结果时间复杂度空间复杂度总结 前言 本题由于没有合适答案为以往遗留问题&#xff0c;最近有时间将以往遗留问题一一完善。 LeetCode - #140 单词拆分 II 不积跬步&#xff0c;无以至千里&#xff1b;不积小流&…

HarmonyOs鸿蒙开发实战(21)=>组件间通信@ohos/liveeventbus

1.简介 LiveEventBus是一款消息总线&#xff0c;具有生命周期感知能力&#xff0c;支持Sticky&#xff0c;支持跨进程&#xff0c;支持跨APP发送消息。 2.下载安装 ohpm install ohos/liveeventbus 3.订阅&#xff0c;注册监听 4.发送事件 5. 完成 > 记得关注博主&#xff…

OpenCV和Qt坐标系不一致问题

“ OpenCV和QT坐标系导致绘图精度下降问题。” OpenCV和Qt常用的坐标系都是笛卡尔坐标系&#xff0c;但是细微处有些不同。 01 — OpenCV坐标系 OpenCV是图像处理库&#xff0c;是以图像像素为一个坐标位置&#xff0c;即一个像素对应一个坐标&#xff0c;所以其坐标系也叫图像…

nohup java -jar supporterSys.jar --spring.profiles.active=prod

文章目录 1、ps -ef | grep java2、kill 13713、ps -ef | grep java4、nohup java -jar supporterSys.jar --spring.profiles.activeprod &5、ps -ef | grep java1. 启动方式进程 1371进程 19994 2. 主要区别3. 可能的原因4. 建议 1、ps -ef | grep java rootshipper:~# p…

Ubuntu上安装MySQL并且实现远程登录

目录 下载网络工具 查看网络连接 更新系统软件包&#xff1b; 安装mysql数据库 查看mysql数据库状态 以数字ip形式显示mysql的监听状态。&#xff08;默认监听端口是3306&#xff09; 查看安装mysql数据库时系统创建的目录信息。 根据查询到的系统用户名以及随机密码&a…

shell编写——脚本传参与运算

shell编写——脚本传参与运算 声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本…

设计模式之 观察者模式

观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听一个主题对象&#xff08;Subject&#xff09;。当主题对象的状态发生变化时&#xff0c;所有依赖于它的观察者都会得到…

深入了解 Linux htop 命令:功能、用法与示例

文章目录 深入了解 Linux htop 命令&#xff1a;功能、用法与示例什么是 htop&#xff1f;htop 的安装htop的基本功能A区&#xff1a;系统资源使用情况B区&#xff1a;系统概览信息C区&#xff1a;进程列表D区&#xff1a;功能键快捷方式 与 top 的对比常见用法与示例实际场景应…

【深度学习】【RKNN】【C++】模型转化、环境搭建以及模型部署的详细教程

【深度学习】【RKNN】【C】模型转化、环境搭建以及模型部署的详细教程 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【RKNN】【C】模型转化、环境搭建以及模型部署的详细教程前言模型转换--pytorch转rknnpytorch转onnxonnx转rkn…

【spark】远程debug spark任务(含有pyspark)

--master yarn和--master client都是可以的。 spark-submit \ --master yarn \ --deploy-mode client \ --name "test-remote-debug" \ --conf "spark.driver.extraJavaOptions-agentlib:jdwptransportdt_socket,servery,suspendn,address5005" \ --conf …

如何使用 Vivado 从源码构建 Infinite-ISP FPGA 项目

如约介绍源码构建 Infinite-ISP 项目&#xff0c;其实大家等的是源码&#xff0c;所以中间过程简洁略过&#xff0c;可以直接翻到文末获取链接。 开源ISP&#xff08;Infinite-ISP&#xff09;介绍 构建工程 第一步&#xff0c;从文末或者下面链接获取源码 https://github.com/…

彻底理解Redis的持久化方式

一.由来 因为Redis之所以能够提供高效读写的操作&#xff0c;是因为它是基于内存的&#xff0c;但是这样也会带来一个问题&#xff0c;及在服务器宕机或者重启的情况下&#xff0c;内存里面的数据就会被丢失掉&#xff0c;所以为了解决这个问题&#xff0c;Redis就提供了持久化…

Bug Fix 20241122:缺少lib文件错误

今天有朋友提醒才突然发现 gitee 上传的代码存在两个很严重&#xff0c;同时也很低级的错误。 因为gitee的默认设置不允许二进制文件的提交&#xff0c; 所以PH47框架下的库文件&#xff08;各逻辑层的库文件&#xff09;&#xff0c;以及Stm32Cube驱动的库文件都没上传到Gi…

NVR管理平台EasyNVR多个NVR同时管理:全方位安防监控视频融合云平台方案

EasyNVR是基于端-边-云一体化架构的安防监控视频融合云平台&#xff0c;具有简单轻量的部署方式与多样的功能&#xff0c;支持多种协议&#xff08;如GB28181、RTSP、Onvif、RTMP&#xff09;和设备类型&#xff08;IPC、NVR等&#xff09;&#xff0c;提供视频直播、录像、回放…

微服务架构:10个实用设计模式

1 微服务架构 微服务架构的重要特征 微服务架构的优点 微服务架构的缺点 何时使用微服务架构 2 微服务架构的设计模式 独享数据库&#xff08;Database per Microservice&#xff09; 事件源&#xff08;Event Sourcing&#xff09; 命令和查询职责分离&#xff08;CQRS&…