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

目录

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

在这里插入图片描述

背景:优先级反转问题

  • 在高优先级任务等待低优先级任务释放资源时,第三个中等优先级任务抢占了低优先级任务。阻塞时间是无法预测的,可能导致高优先级任务无法满足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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【京东API】商品详情+搜索商品列表接口

利用电商API获取数据的步骤 1.申请API接口&#xff1a;首先要在相应电商平台上注册账号并申请API接口。 2.获取授权&#xff1a;在账号注册成功后&#xff0c;需要获取相应的授权才能访问电商API。 3.调用API&#xff1a;根据电商API提供的请求格式&#xff0c;通过编程实现…

8.GC基本原理

目录 概述垃圾回收引用计数法 (Reference Counting)根可达分析算法 (GCRooting Tracing)对象引用类型强引用软引用弱引用 清除垃圾1.标记-清除算法 (Mark-Sweep)2.复制算法 (Copying)3.标记-整理算法 (Mark-Compact)分代回收 (Generational Collection) 垃圾回收器GC-串行收集器…

力扣每日一题-K个元素的最大和-2023.11.15

力扣每日一题&#xff1a;K个元素的最大和 题目链接:2656.K个元素的最大和 题目描述 代码思路 题目看完直接笑嘻了&#xff0c;还有这么容易的题。由题可知&#xff0c;第一次要找出最大值m&#xff0c;那由于把m1放回去&#xff0c;那第二次找的就是m1&#xff0c;以此类推…

DGL如何表征一张图

有关于DGL中图的构建 DGL 将有向图表示为一个 DGL 图对象。图中的节点编号连续&#xff0c;从0开始。我们一般通过指定图中的节点数&#xff0c;以及源节点和目标节点的列表&#xff0c;来构建这么一个图。 下面的代码构造了一个图&#xff0c;这个图有五个叶子节点。中心节点…

python 多线程池 CPU拉满

前言&#xff1a; 关于多线程的博客先前的博客如下&#xff1a; python线程join方法_python 线程join-CSDN博客 【精选】Python GIL锁_python gil 锁-CSDN博客 python函数运行加速_python os.listdir速度慢_两只蜡笔的小新的博客-CSDN博客 只需下面的模版即可: from multi…

CNCC 2023收官,Milvus Cloud与行业大咖共话向量数据库系统

近期,CNCC 2023 在沈阳圆满结束,紧凑、前沿的 129 场技术论坛让人印象深刻。据悉,这 129 场技术论坛涵盖人工智能、安全、计算+、软件工程、教育、网络、芯片、云计算等 30 余个方向。Zilliz 受邀参与【智能时代的大数据系统】技术论坛。 智能时代的到来,无疑给社会经济和日…

前端 vue 面试题 (一)

文章目录 v-if,v-show差别v-for和v-if虚拟dom解决什么问题vue的data为什么返回函数不返回对象比较vue&#xff0c;reactvue双向绑定原理vue虚拟dom 的diff算法vue 虚拟dom的diff算法的时间复杂度vue2与vue3的区别vue数据缓存&#xff0c;避免重复计算单页应用怎么跨页面传参vue…

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

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

队列与堆栈:原理、区别、算法效率和应用场景的探究

队列与堆栈&#xff1a;原理、区别、算法效率和应用场景的探究 前言原理与应用场景队列原理应用场景&#xff1a; 堆栈原理应用场景递归原理和堆栈在其中的作用递归原理堆栈作用 队列与堆栈区别队列堆栈算法效率 前言 本文主要讲解数据结构中队列和堆栈的原理、区别以及相关的…

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

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

0基础学习VR全景平台篇第121篇:认识视频剪辑软件Premiere

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 大家好&#xff0c;这节课是带领大家认识认识我们的剪辑软件Premiere&#xff0c;一般简称是PR。 &#xff08;PR界面&#xff09; 我们首先打开PR&#xff0c;第一步就是要创建…

滚雪球学Java(64):LinkedHashSet原理及实现解析

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

【数据结构】堆(Heap):堆的实现、堆排序、TOP-K问题

目录 堆的概念及结构 ​编辑 堆的实现 实现堆的接口 堆的初始化 堆的打印 堆的销毁 获取最顶的根数据 交换 堆的插入&#xff08;插入最后&#xff09; 向上调整&#xff08;这次用的是小堆&#xff09; 堆的删除&#xff08;删除根&#xff09; 向下调整&#xff08;这次用的…

dgl 的cuda 版本 环境配置(dgl cuda 版本库无法使用问题解决)

1. 如果你同时有dgl dglcu-XX.XX 那么&#xff0c;应该只会运行dgl &#xff08;DGL的CPU版本&#xff09;&#xff0c;因此&#xff0c;你需要把dgl(CPU)版本给卸载了 但是我只卸载CPU版本还不够&#xff0c;我GPU 版本的dglcu依旧不好使&#xff0c;因此吧GPU版本的也得卸载…

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

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

2.5 Windows驱动开发:DRIVER_OBJECT对象结构

在Windows内核中&#xff0c;每个设备驱动程序都需要一个DRIVER_OBJECT对象&#xff0c;该对象由系统创建并传递给驱动程序的DriverEntry函数。驱动程序使用此对象来注册与设备对象和其他系统对象的交互&#xff0c;并在操作系统需要与驱动程序进行交互时使用此对象。DRIVER_OB…

云服务器如何选?腾讯云2核2G3M云服务器88元一年!

作为一名程序员&#xff0c;在选择云服务器时&#xff0c;我们需要关注几个要点&#xff1a;网络稳定性、价格以及云服务商的规模。这些要素将直接影响到我们的使用体验和成本效益。接下来&#xff0c;我将为大家推荐一款性价比较高的轻应用云服务器。 腾讯云双11活动 腾讯云…

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

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

Git用pull命令后再直接push有问题

在gitlab新建一个项目&#xff0c;然后拉取到本地&#xff0c;用&#xff1a; git init git pull <远程主机名> 然后就是在本地工作区增加所有文件及文件夹。再添加、提交&#xff0c;都没问题&#xff1a; 但是&#xff0c;git push出问题&#xff1a; 说明本地仓库和…

手把手带你学习 JavaScript 的 ES6 ~ ESn

文章目录 一、引言二、了解 ES6~ESn 的新特性三、掌握 ES6~ESn 的用法和实现原理四、深入挖掘和拓展《深入理解现代JavaScript》编辑推荐内容简介作者简介精彩书评目录 一、引言 JavaScript 是一种广泛使用的网络编程语言&#xff0c;它在前端开发中扮演着重要角色。随着时间的…