【freertos-kernel】list

freertos list

  • 基本类型
  • 结构体
    • ListItem_t (list.h)
    • List_t (list.h)
  • 宏函数
  • 函数
    • vListInitialise
    • vListInitialiseItem
    • vListInsertEnd
    • vListInsert
    • uxListRemove

基本类型

freertos为了兼容性,重新定义了基本类型,像BaseType_t,TickType_t等等,这些定义都在portable文件夹下对应编译器文件夹下对应内核文件夹的portmacro.h里。比如armcm3下的BaseType_t就是long类型,我一直以为long是64位,就很奇怪,不应该是32位吗,问了ai查了资料后才明白了,了解到数据模型。重新定义基本类型可以屏蔽cpu内核和编译器对数据类型位数的影响,为了让常用数据类型与cpu位数匹配。看到这我也是第一次对这个问题比以前有更深入一点的研究,为了统一理解,引入了 数据模型 ,有ILP32,LP64,LLP64等等,I表示int,L表示long,P表示指针类型,比如ILP32就是int,long,指针都是32位的,主要是解决一些有位数差异的类型。

结构体

ListItem_t (list.h)

链表节点

struct xLIST_ITEM
{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUEconfigLIST_VOLATILE TickType_t xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;void * pvOwner;struct xLIST * configLIST_VOLATILE pxContainer;listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
};
typedef struct xLIST_ITEM ListItem_t;#if ( configUSE_MINI_LIST_ITEM == 1 )struct xMINI_LIST_ITEM{listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUEconfigLIST_VOLATILE TickType_t xItemValue;struct xLIST_ITEM * configLIST_VOLATILE pxNext;struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;};typedef struct xMINI_LIST_ITEM MiniListItem_t;
#elsetypedef struct xLIST_ITEM      MiniListItem_t;
#endif
  • listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUElistSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE见名知义,链表节点完整性检查值,具体定义在本结构体定义的前面,如果configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES配置为1的时候这两个宏会被定义成TickType_t的字段,如果配置为0就啥也没有。
  • 关于configLIST_VOLATILE的说明在list.h开头,链表结构体的成员变量是从中断中被修改的,因此从理论上来说应该将它们声明为 volatile。然而,这些成员变量仅在“功能上是原子性”的方式下被修改(即在临界区或调度器挂起期间进行修改),并且它们要么是通过引用传入函数的,要么是通过一个 volatile 变量进行索引访问的。因此,在目前为止测试的所有使用场景中,可以省略 volatile 修饰符,从而带来一定程度的性能提升,而不会对功能行为产生不良影响。目前为止IAR、ARM 和 GCC 编译器在设置为最大优化级别时所生成的汇编指令已经被检查过,可以不加,但是随着编译器的发展可能会被错误优化,遇到这种情况可以在FreeRTOSConfig.h添加#define configLIST_VOLATILE volatile
  • pxNext指向下一个节点。pxPrevious指向前一个结点。pvOwner指向一些与节点相关的其他数据,可能指向任务控制块等,pxContainer指向当前链表项所属的链表,可用于判断该项是否已加入某个链表。xItemValue节点值 我猜测可能和任务分配时间有关
  • 还提供了一种迷你链表节点,去除了pvOwnerpxContainer两个字段,只保留了链表结构部分。

List_t (list.h)

给调度器使用的链表。

typedef struct xLIST
{listFIRST_LIST_INTEGRITY_CHECK_VALUE	//完成性检查值configLIST_VOLATILE UBaseType_t uxNumberOfItems;ListItem_t * configLIST_VOLATILE pxIndex;MiniListItem_t xListEnd;listSECOND_LIST_INTEGRITY_CHECK_VALUE	//完成性检查值
} List_t;
  • uxNumberOfItems当前链表中的节点数量。pxIndex用于遍历链表的指针,相当于一个游标。xListEnd是特殊的链表节点,从源码注释来看,xItemValue是最大可能值,它永远位于链表末尾,作为结束标记(从这里的意思可以看出这里的链表可能是升序排序的,后面看调度器的代码应该就清楚了)。

宏函数

比较简单,根据名字就基本知道功能,简单罗列一下。

  • listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )
    设置链表节点pxListItem的pxOwner为pxOwner
  • listGET_LIST_ITEM_OWNER( pxListItem )
    返回pxListItem的pvOwner
  • listSET_LIST_ITEM_VALUE( pxListItem, xValue )
    设置pxListItem的值xItemValue为xValue
  • listGET_LIST_ITEM_VALUE( pxListItem )
    返回pxListItem的值xItemValue
  • listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList )
    返回pxList 的头节点的值xItemValue
  • listGET_HEAD_ENTRY( pxList )
    返回pxList 的头节点,也是尾节点的下一个节点,可以看出是个双向循环链表
  • listGET_NEXT( pxListItem )
    返回pxListItem的下一个节点
  • listGET_END_MARKER( pxList )
    返回pxList 的尾节点
  • listLIST_IS_EMPTY( pxList )
    返回链表是否为空
  • listCURRENT_LIST_LENGTH( pxList )
    返回链表长度
  • listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )
    返回下一个节点(跳过尾节点)的pvOwner给pxTCB
  • listREMOVE_ITEM( pxItemToRemove )
    移除pxItemToRemove节点,把pxIndex移到pxItemToRemove 前一个节点
  • listINSERT_END( pxList, pxNewListItem )
    尾部插入pxNewListItem
  • listGET_OWNER_OF_HEAD_ENTRY( pxList )
    返回头节点的pvOwner
  • listIS_CONTAINED_WITHIN( pxList, pxListItem )
    pxList是否包含pxListItem
  • listLIST_IS_INITIALISED( pxList )
    pxList 是否初始化了

函数

这些函数的声明都有PRIVILEGED_FUNCTION宏,特权函数,类似的宏还有特权变量,定义在mpu_wrapper.h
#define PRIVILEGED_FUNCTION attribute( ( section( “privileged_functions” ) ) )
特权函数会分配到特殊的段,为MPU(内存保护单元)提供支持。

vListInitialise


void vListInitialise( List_t * const pxList )
{traceENTER_vListInitialise( pxList );	//调试用的好像,先不管他pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );	//游标指向尾节点listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );//设置节点完整性检查值为1pxList->xListEnd.xItemValue = portMAX_DELAY;pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );#if ( configUSE_MINI_LIST_ITEM == 0 ){pxList->xListEnd.pvOwner = NULL;pxList->xListEnd.pxContainer = NULL;listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );}#endifpxList->uxNumberOfItems = ( UBaseType_t ) 0U;listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );traceRETURN_vListInitialise();
}

初始化链表,初始化链表尾节点。

vListInitialiseItem

void vListInitialiseItem( ListItem_t * const pxItem )
{traceENTER_vListInitialiseItem( pxItem );/* Make sure the list item is not recorded as being on a list. */pxItem->pxContainer = NULL;/* Write known values into the list item if* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );traceRETURN_vListInitialiseItem();
}

没啥好说的

vListInsertEnd

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
{ListItem_t * const pxIndex = pxList->pxIndex;traceENTER_vListInsertEnd( pxList, pxNewListItem );listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );pxNewListItem->pxNext = pxIndex;pxNewListItem->pxPrevious = pxIndex->pxPrevious;/* Only used during decision coverage testing. */mtCOVERAGE_TEST_DELAY();pxIndex->pxPrevious->pxNext = pxNewListItem;pxIndex->pxPrevious = pxNewListItem;/* Remember which list the item is in. */pxNewListItem->pxContainer = pxList;( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems + 1U );traceRETURN_vListInsertEnd();
}

在pxIndex后面插入新的节点

vListInsert

void vListInsert( List_t * const pxList,ListItem_t * const pxNewListItem )
{ListItem_t * pxIterator;const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;traceENTER_vListInsert( pxList, pxNewListItem );listTEST_LIST_INTEGRITY( pxList );listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );if( xValueOfInsertion == portMAX_DELAY ){pxIterator = pxList->xListEnd.pxPrevious;}else{for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ){/* There is nothing to do here, just iterating to the wanted* insertion position. */}}pxNewListItem->pxNext = pxIterator->pxNext;pxNewListItem->pxNext->pxPrevious = pxNewListItem;pxNewListItem->pxPrevious = pxIterator;pxIterator->pxNext = pxNewListItem;pxNewListItem->pxContainer = pxList;( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems + 1U );traceRETURN_vListInsert();
}

将一个新的节点按其 xItemValue 的大小顺序插入到链表中,保持链表始终按升序排列。

uxListRemove

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
{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();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.pswp.cn/diannao/84124.shtml

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

相关文章

游戏盾的功有哪些?

游戏盾的功能主要包括以下几方面&#xff1a; 一、网络攻击防护 DDoS攻击防护&#xff1a; T级防御能力&#xff1a;游戏盾提供分布式云节点防御集群&#xff0c;可跨地区、跨机房动态扩展防御能力和负载容量&#xff0c;轻松达到T级别防御&#xff0c;有效抵御SYN Flood、UD…

PycharmFlask 学习心得:路由(3-4)

对路由的理解&#xff1a; 用户输入网址 例如&#xff1a;http://localhost:5000/hello 浏览器会向这个地址发起一个 HTTP 请求&#xff08;比如 GET 请求&#xff09; 请求到达 Flask 的服务器 Flask 监听着某个端口&#xff08;如 5000&#xff09;&#xff0c;收到请求后…

课程与考核

6.1 课程讲解与实战考核 6.1.1 SQL注入篇考核 考核目标&#xff1a;通过手动注入与工具结合&#xff0c;获取目标数据库敏感信息。 题目示例&#xff1a; 目标URL&#xff1a;http://vuln-site.com/product?id1 要求&#xff1a; 判断注入类型&#xff08;联合查询/报错注…

线程池介绍,分类,实现(工作原理,核心组成,拒绝策略),固态线程池的实现+详细解释(支持超时取消机制和不同的拒绝策略)

目录 线程池 介绍 分类 实现 工作原理 核心组成 拒绝策略 固态线程池 功能 std::future 实现 拒绝策略支持 提交任务 超时取消 用户检测取消 安全销毁 代码 测试 线程池 介绍 线程池(图解,本质,模拟实现代码),添加单例模式(懒汉思路代码)_线程池单例-CSDN博…

纺线机与PLC通讯故障?ETHERCAT/CANopen网关秒解协议难题

在纺织行业智能化转型浪潮中&#xff0c;设备间高效通信是实现自动化生产的关键。JH-ECT009疆鸿智能EtherCAT转CANopen协议转换网关&#xff0c;凭借出色的协议适配能力&#xff0c;成功架起倍福PLC与自动纺线机间的通信桥梁&#xff0c;为纺织厂自动化生产注入强劲动力。 纺织…

深度剖析并发I/O模型select、poll、epoll与IOCP核心机制

核心概要&#xff1a;select、poll、epoll 和 IOCP 是四种用于提升服务器并发处理能力的I/O模型或机制。前三者主要属于I/O多路复用范畴&#xff0c;允许单个进程或线程监视多个I/O流的状态&#xff1b;而 IOCP 则是一种更为彻底的异步I/O模型。 一、引言&#xff1a;为何需要这…

microsoft中word如何添加个人签名

https://support.microsoft.com/zh-cn/office/%E6%8F%92%E5%85%A5%E7%AD%BE%E5%90%8D-f3b3f74c-2355-4d53-be89-ae9c50022730 插入签名图片 图片格式选择裁剪合适的大小 使用的签名如果不是白色纸张的话可以重新着色 依次点击图片格式——颜色——重新着色——黑白50% 设置透…

linux初识--基础指令

Linux下基础指令 ls 指令 语法&#xff1a; ls [ 选项 ] [ ⽬录或⽂件 ] 功能&#xff1a;对于⽬录&#xff0c;该命令列出该⽬录下的所有⼦⽬录与⽂件。对于⽂件&#xff0c;将列出⽂件名以及其他信 息。 常⽤选项&#xff1a; -a 列出⽬录下的所有⽂件&#xff0c;包括以…

实战:Dify智能体+Java=自动化运营工具!

我们在运营某个圈子的时候&#xff0c;可能每天都要将这个圈子的“热门新闻”发送到朋友圈或聊天群里&#xff0c;但依靠传统的实现手段非常耗时耗力&#xff0c;我们通常要先收集热门新闻&#xff0c;再组装要新闻内容&#xff0c;再根据内容设计海报等。 那怎么才能简化并高…

RabbitMQ可靠传输——持久性、发送方确认

一、持久性 前面学习消息确认机制时&#xff0c;是为了保证Broker到消费者直接的可靠传输的&#xff0c;但是如果是Broker出现问题&#xff08;如停止服务&#xff09;&#xff0c;如何保证消息可靠性&#xff1f;对此&#xff0c;RabbitMQ提供了持久化功能&#xff1a; 持久…

(Java基础笔记vlog)Java中常见的几种设计模式详解

前言&#xff1a; 在 Java 编程里&#xff0c;设计模式是被反复使用、多数人知晓、经过分类编目的代码设计经验总结。他能帮助开发者更高效地解决常见问题&#xff0c;提升代码的可维护性、可扩展性和复用性。下面介绍Java 中几种常见的设计模式。 单例模式&#xff08;Singlet…

(8)Spring Boot 原生镜像支持

Spring Boot 原生镜像支持 👉 点击展开题目 在Spring Boot 3.x中,如何设计一个支持GraalVM原生镜像的微服务?需要特别注意哪些限制? 📌 Spring Boot 3.x 原生镜像概述 Spring Boot 3.x 通过 Spring Native 项目提供了对 GraalVM 原生镜像的一流支持,使开发者能够将 S…

不使用SOAP,从PDF表单连接数据库

不使用SOAP协议&#xff0c;通过XFDF格式实现PDF表单与数据库交互的方法。该方法兼容免费的Adobe Reader&#xff0c;且无需特殊权限设置。 背景与问题 历史方案: Adobe曾提供ADBC接口&#xff08;基于ODBC&#xff09;&#xff0c;但在Acrobat 9后被移除。SOAP方案在免费版Rea…

HTTP由浅入深

文章目录 概述特点URL HTTP 与 HTTPS概述HTTP 工作原理HTTPS 的作用区别总结 请求报文请求行常见请求方法请求头请求体Content-Type 详解常见场景 Content-Type 对应关系 响应报文响应行状态码详解1xx&#xff1a;信息响应&#xff08;Informational&#xff09;2xx&#xff1a…

Redis淘汰策略

Redis有八种淘汰策略 noeviction &#xff1a;不进行淘汰&#xff0c;直接报错。allkeys-lru &#xff1a;随机淘汰最久未使用的键。volatile-lru &#xff1a;从设置了过期时间的键中&#xff0c;随机淘汰最久未使用的键。allkeys-random &#xff1a;随机淘汰某个键。volati…

Maven打包SpringBoot项目,因包含SpringBootTest单元测试和Java预览版特性导致打包失败

SpringBoot启用Java预览版特性&#xff08;无测试类&#xff09; 在pom.xml文件中加入以下配置表示启用Java预览版 <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration>…

Makefile快速入门

简介‌&#xff1a; ‌ Makefile‌ 是一种用于自动化构建和管理软件项目的工具文件&#xff0c;通常与 make 命令配合使用。它通过定义‌规则‌&#xff08;rules&#xff09;来指定如何从源文件生成目标文件&#xff08;如可执行程序或库&#xff09;&#xff0c;并自动…

RISC-V 开发板 MUSE Pi Pro OpenCV结合Gstreamer实时显示CSI摄像头

视频讲解&#xff1a;RISC-V 开发板 MUSE Pi Pro OpenCV结合Gstreamer实时显示CSI摄像头_哔哩哔哩_bilibili RISC-V 开发板 MUSE Pi Pro OpenCV结合Gstreamer实时显示CSI摄像头 安装opencv相关库 sudo apt install libopencv-dev python3 python3-opencv 测试使用的CSI摄像头…

如何用JAVA手写一个Tomcat

一、初步理解Tomcat Tomcat是什么&#xff1f; Tomcat 是一个开源的 轻量级 Java Web 应用服务器&#xff0c;核心功能是 运行 Servlet/JSP。 Tomcat的核心功能&#xff1f; Servlet 容器&#xff1a;负责加载、实例化、调用和销毁 Servlet。 HTTP 服务器&#xff1a;监听端口…

短剧系统开发与抖音生态融合:短视频时代的新风口与商业机遇

在短视频内容井喷的时代&#xff0c;“短剧”作为一种新兴内容形态&#xff0c;正以惊人的速度抢占用户注意力。抖音、快手等平台日均播放量破亿的短剧作品&#xff0c;不仅催生了新的内容创作风口&#xff0c;更推动了短剧系统开发的巨大市场需求。本文将深度解析短剧系统开发…