μC/OS-II---互斥信号量管理2(os_mutex.c)

news2024/11/20 0:31:20

目录

  • 背景:优先级反转问题
  • 互斥信号量管理
    • 互斥信号量发出(释放)
    • 互斥信号量获取/无等待
    • 互斥信号量状态查询

在这里插入图片描述

背景:优先级反转问题

  • 在高优先级任务等待低优先级任务释放资源时,第三个中等优先级任务抢占了低优先级任务。阻塞时间是无法预测的,可能导致高优先级任务无法满足deadline。这是需要解决的问题。μC/OS-II采用的办法:优先级继承协议。【实际采用的方法是由互斥信号量先预占一个优先级】

互斥信号量管理

互斥信号量发出(释放)

INT8U  OSMutexPost (OS_EVENT *pevent)
{
	INT8U      pcp;                                   /* Priority ceiling priority                     */
	INT8U      prio;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
	OS_CPU_SR  cpu_sr = 0u;
#endif
	
	if (OSIntNesting > 0u)                            /* See if called from ISR ...                    */
	{
		return (OS_ERR_POST_ISR);                     /* ... can't POST mutex from an ISR              */
	}
	
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                      /* Validate 'pevent'                             */
	{
		return (OS_ERR_PEVENT_NULL);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX)   /* Validate event block type                     */
	{
		return (OS_ERR_EVENT_TYPE);
	}
	
	OS_ENTER_CRITICAL();
	pcp  = (INT8U) (pevent->OSEventCnt >> 8u);        /* Get priority ceiling priority of mutex        */
	prio = (INT8U) (pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's original priority      */
	
	if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr)     /* See if posting task owns the MUTEX            */
	{
		OS_EXIT_CRITICAL();
		return (OS_ERR_NOT_MUTEX_OWNER);
	}
	
	if (pcp != OS_PRIO_MUTEX_CEIL_DIS)
	{
		if (OSTCBCur->OSTCBPrio == pcp)               /* Did we have to raise current task's priority? */
		{
			OSMutex_RdyAtPrio (OSTCBCur, prio);       /* Restore the task's original priority          */
		}
		
		OSTCBPrioTbl[pcp] = OS_TCB_RESERVED;          /* Reserve table entry                           */
	}
	
	if (pevent->OSEventGrp != 0u)                     /* Any task waiting for the mutex?               */
	{
		/* Yes, Make HPT waiting for mutex ready         */
		prio                = OS_EventTaskRdy (pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK);
		pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;  /*      Save priority of mutex's new owner       */
		pevent->OSEventCnt |= prio;
		pevent->OSEventPtr  = OSTCBPrioTbl[prio];     /*      Link to new mutex owner's OS_TCB         */
		
		if ((pcp  != OS_PRIO_MUTEX_CEIL_DIS) &&
				(prio <= pcp))                            /*      PCP 'must' have a SMALLER prio ...       */
		{
			OS_EXIT_CRITICAL();                       /*      ... than current task!                   */
			OS_Sched();                               /*      Find highest priority task ready to run  */
			return (OS_ERR_PCP_LOWER);
		}
		
		else
		{
			OS_EXIT_CRITICAL();
			OS_Sched();                               /*      Find highest priority task ready to run  */
			return (OS_ERR_NONE);
		}
	}
	
	pevent->OSEventCnt |= OS_MUTEX_AVAILABLE;         /* No,  Mutex is now available                   */
	pevent->OSEventPtr  = (void *)0;
	OS_EXIT_CRITICAL();
	return (OS_ERR_NONE);
}

互斥信号量获取/无等待

#if OS_MUTEX_ACCEPT_EN > 0u
BOOLEAN  OSMutexAccept (OS_EVENT  *pevent,
												INT8U     *perr)
{
	INT8U      pcp;                                    /* Priority Ceiling Priority (PCP)              */
#if OS_CRITICAL_METHOD == 3u                           /* Allocate storage for CPU status register     */
	OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
	
	if (perr == (INT8U *)0)
	{
		OS_SAFETY_CRITICAL_EXCEPTION();
		return (OS_FALSE);
	}
	
#endif
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                       /* Validate 'pevent'                            */
	{
		*perr = OS_ERR_PEVENT_NULL;
		return (OS_FALSE);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX)    /* Validate event block type                    */
	{
		*perr = OS_ERR_EVENT_TYPE;
		return (OS_FALSE);
	}
	
	if (OSIntNesting > 0u)                             /* Make sure it's not called from an ISR        */
	{
		*perr = OS_ERR_PEND_ISR;
		return (OS_FALSE);
	}
	
	OS_ENTER_CRITICAL();                               /* Get value (0 or 1) of Mutex                  */
	pcp = (INT8U) (pevent->OSEventCnt >> 8u);          /* Get PCP from mutex                           */
	
	if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE)
	{
		pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;   /*      Mask off LSByte (Acquire Mutex)         */
		pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;     /*      Save current task priority in LSByte    */
		pevent->OSEventPtr  = (void *)OSTCBCur;        /*      Link TCB of task owning Mutex           */
		
		if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) &&
				(OSTCBCur->OSTCBPrio <= pcp))              /*      PCP 'must' have a SMALLER prio ...      */
		{
			OS_EXIT_CRITICAL();                       /*      ... than current task!                  */
			*perr = OS_ERR_PCP_LOWER;
		}
		
		else
		{
			OS_EXIT_CRITICAL();
			*perr = OS_ERR_NONE;
		}
		
		return (OS_TRUE);
	}
	
	OS_EXIT_CRITICAL();
	*perr = OS_ERR_NONE;
	return (OS_FALSE);
}
#endif

互斥信号量状态查询

#if OS_MUTEX_QUERY_EN > 0u
INT8U  OSMutexQuery (OS_EVENT       *pevent,
										 OS_MUTEX_DATA  *p_mutex_data)
{
	INT8U       i;
	OS_PRIO    *psrc;
	OS_PRIO    *pdest;
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register           */
	OS_CPU_SR   cpu_sr = 0u;
#endif
	
	if (OSIntNesting > 0u)                                 /* See if called from ISR ...               */
	{
		return (OS_ERR_QUERY_ISR);                         /* ... can't QUERY mutex from an ISR        */
	}
	
#if OS_ARG_CHK_EN > 0u
	
	if (pevent == (OS_EVENT *)0)                           /* Validate 'pevent'                        */
	{
		return (OS_ERR_PEVENT_NULL);
	}
	
	if (p_mutex_data == (OS_MUTEX_DATA *)0)                /* Validate 'p_mutex_data'                  */
	{
		return (OS_ERR_PDATA_NULL);
	}
	
#endif
	
	if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX)        /* Validate event block type                */
	{
		return (OS_ERR_EVENT_TYPE);
	}
	
	OS_ENTER_CRITICAL();
	p_mutex_data->OSMutexPCP  = (INT8U) (pevent->OSEventCnt >> 8u);
	p_mutex_data->OSOwnerPrio = (INT8U) (pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8);
	
	if (p_mutex_data->OSOwnerPrio == 0xFFu)
	{
		p_mutex_data->OSValue = OS_TRUE;
	}
	
	else
	{
		p_mutex_data->OSValue = OS_FALSE;
	}
	
	p_mutex_data->OSEventGrp  = pevent->OSEventGrp;        /* Copy wait list                           */
	psrc                      = &pevent->OSEventTbl[0];
	pdest                     = &p_mutex_data->OSEventTbl[0];
	
	for (i = 0u; i < OS_EVENT_TBL_SIZE; i++)
	{
		*pdest++ = *psrc++;
	}
	
	OS_EXIT_CRITICAL();
	return (OS_ERR_NONE);
}
#endif

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

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

相关文章

【JY】ANSYS Workbench在减隔震应用分析中的单元积分技术笔记

写在前文 尽管减隔震技术与有限元结合取得了众多成果&#xff0c;但仍面临诸多挑战&#xff0c;如材料非线性、模型不确定性等等。减隔震设计除了常规的宏观结构设计采用SAP2000、Etabs、Midas、SSG、Paco-SAP 或 YJK\PKPM等。 【JY】各类有限元软件计算功能赏析与探讨 我们需要…

解析数据洁净之道:BI中数据清理对见解的深远影响

本文由葡萄城技术团队发布。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 随着数字化和信息化进程的不断发展&#xff0c;数据已经成为企业的一项不可或缺的重要资源。然而&#xff0c;这…

Linux常用命令——bzgrep命令

在线Linux命令查询工具 bzgrep 使用正则表达式搜索.bz2压缩包中文件 补充说明 bzgrep命令使用正则表达式搜索“.bz2”压缩包中文件&#xff0c;将匹配的行显示到标注输出。 语法 bzgrep(参数)参数 搜索模式&#xff1a;指定要搜索的模式&#xff1b;.bz2文件&#xff1a…

Linux系统简介与开源精神

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Linux系统理论 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言&#x1f324;️Linux系统背景☁️UNIX发展史☁️Linux发展史☁️Linux系统企业应用现…

基于springboot实现校园医疗保险管理系统【项目源码】

基于springboot实现校园医疗保险管理系统演示 系统开发平台 在线校园医疗保险系统中&#xff0c;Eclipse能给用户提供更多的方便&#xff0c;其特点一是方便学习&#xff0c;方便快捷&#xff1b;二是有非常大的信息储存量&#xff0c;主要功能是用在对数据库中查询和编程。其…

2.6 Windows驱动开发:使用IO与DPC定时器

本章将继续探索驱动开发中的基础部分&#xff0c;定时器在内核中同样很常用&#xff0c;在内核中定时器可以使用两种&#xff0c;即IO定时器&#xff0c;以及DPC定时器&#xff0c;一般来说IO定时器是DDK中提供的一种&#xff0c;该定时器可以为间隔为N秒做定时&#xff0c;但如…

vue-组件通信(动态组件)

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue-组件通信|动态组件 目录 组件通信 1.父传子 2.子传父 3.ref 4.兄弟组件 5.跨层级 provid…

【ROS导航Navigation】二 | 坐标系 | 定位 | 导航约束

目录 致谢&#xff1a;ROS赵虚左老师 一、通过里程计定位 二、通过传感器定位 三、坐标系变换 四、导航约束条件 1.硬件 2.软件 致谢&#xff1a;ROS赵虚左老师 Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 参考赵虚左老师的实战教程 一、…

算不上最全,但都是必备——Redis这些不会不行啊

Redis篇 数据类型及其业务场景 字符串&#xff08;String&#xff09; 字符串类型是最基本的数据类型&#xff0c;value 最多可以容纳的数据长度是 512M。 存储任意类型的数据&#xff0c;包括数字、文本等。适用于缓存、计数器、分布式锁等场景。共享 Session 信息 哈希&am…

基于springboot实现学生选课平台管理系统项目【项目源码】

系统开发平台 在该地方废物回收机构管理系统中&#xff0c;Eclipse能给用户提供更多的方便&#xff0c;其特点一是方便学习&#xff0c;方便快捷&#xff1b;二是有非常大的信息储存量&#xff0c;主要功能是用在对数据库中查询和编程。其功能有比较灵活的数据应用&#xff0c…

基于springboot实现校园医疗保险管理系统【项目源码】计算机毕业设计

基于springboot实现校园医疗保险管理系统演示 系统开发平台 在线校园医疗保险系统中&#xff0c;Eclipse能给用户提供更多的方便&#xff0c;其特点一是方便学习&#xff0c;方便快捷&#xff1b;二是有非常大的信息储存量&#xff0c;主要功能是用在对数据库中查询和编程。其…

IDEA-git commit log 线

一、本地代码颜色标识 红色&#xff1a;新建的文件&#xff0c;没有add到git本地仓库蓝色&#xff1a;修改的文件&#xff0c;没有提交到git远程仓库绿色&#xff1a;已添加到git本地仓库&#xff0c;没有提交到git远程仓库灰色&#xff1a;删除的文件&#xff0c;没有提交到g…

Linux Docker 图形化工具 Portainer远程访问

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

Python武器库开发-flask篇之路由和视图函数(二十二)

flask篇之路由和视图函数(二十二) 通过创建路由并关联函数&#xff0c;实现一个基本的网页&#xff1a; #!/usr/bin/env python3 from flask import Flask# 用当前脚本名称实例化Flask对象&#xff0c;方便flask从该脚本文件中获取需要的内容 app Flask(__name__)#程序实例需…

【移远QuecPython】EC800M物联网开发板的SIM卡初始化和网络状态检测

【移远QuecPython】EC800M物联网开发板的SIM卡初始化和网络状态检测 文章目录 SIM卡初始化导入库获取SIM状态 网络检测导入库等待网络就绪 函数打包附录&#xff1a;列表的赋值类型和py打包列表赋值BUG复现代码改进优化总结 py打包 SIM卡初始化 导入库 import sim获取SIM状态…

java入门, 记录检测网络

一、需求 在开发中&#xff0c;我们经常需要本地连接服务器&#xff0c;或者数据库这些机器或者组件&#xff0c;但是有时候网络不通&#xff0c;我们怎样检测&#xff0c;除了ping 和 telnet 还需要那些常用的技能。 二、检测网络 1、一般我们先ping一些需要连接的网络ip 或…

msys2 + MSVC(VS2019)编译ffmpeg6.0源码

以前使用的v1.2版&#xff0c;很多功能和使用方法发生了变化&#xff0c;需要重新编译新的ffmpeg版。 编译环境: windows 10 , VS2019, MSYS2 1. msys2 下载安装 MSYS2 , https://www.msys2.org/ 2. msys2 环境配置打开 msys2 2.1 安装相关软件 然后输入以下命令安装&…

C++命名空间,函数重载

一、C命名空间 使用过C的人都知道在引入<iostream>头文件后需要加上这样一行代码 using namespace std; 但是对于初学者来说不仔细研究一下可能都不知道为什么需要这样一行代码&#xff0c;接下来将对其进行解释&#xff0c;引入命名空间的概念 C在C的基础上增加了命…

C语言--每日五道选择题--Day12

第一题 1、如下程序的功能是&#xff08; &#xff09; #include <stdio.h> int main() {char ch[80] "123abcdEFG*&";int j;puts(ch);for(j 0; ch[j] ! \0; j){if(ch[j] > A && ch[j] < Z){ch[j] ch[j] e - E;}}puts(ch);return 0; } A…

Spring-boot Mybatis-plus 实战应用

文章目录 前言一、springBoot 集成mybatis-plus1.1 maven 引入依赖&#xff1a;1.2 配置数据源&#xff1a;&#xff1a; 二、使用:2.1 mysql 打印执行的sql 设置&#xff1a;2.2 分页查询&#xff1a;2.3 条件构造器&#xff1a;2.3.1 QueryWrapper 查询&#xff1a;2.3.2 Upd…