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

目录

  • 背景:优先级反转问题
  • 互斥信号量管理
    • 互斥信号量创建
    • 互斥信号量删除
    • 互斥信号量获取/等待

在这里插入图片描述

背景:优先级反转问题

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

互斥信号量管理

互斥信号量创建

OS_EVENT  *OSMutexCreate (INT8U   prio,INT8U  *perr)
{OS_EVENT  *pevent;
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0){OS_SAFETY_CRITICAL_EXCEPTION();return ((OS_EVENT *)0);}#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE){OS_SAFETY_CRITICAL_EXCEPTION();return ((OS_EVENT *)0);}#endif
#if OS_ARG_CHK_EN > 0uif (prio != OS_PRIO_MUTEX_CEIL_DIS){if (prio >= OS_LOWEST_PRIO)                        /* Validate PCP                             */{*perr = OS_ERR_PRIO_INVALID;return ((OS_EVENT *)0);}}#endifif (OSIntNesting > 0u)                                 /* See if called from ISR ...               */{*perr = OS_ERR_CREATE_ISR;                         /* ... can't CREATE mutex from an ISR       */return ((OS_EVENT *)0);}OS_ENTER_CRITICAL();if (prio != OS_PRIO_MUTEX_CEIL_DIS){if (OSTCBPrioTbl[prio] != (OS_TCB *)0)             /* Mutex priority must not already exist    */{OS_EXIT_CRITICAL();                            /* Task already exist at priority ...       */*perr = OS_ERR_PRIO_EXIST;                      /* ... ceiling priority                     */return ((OS_EVENT *)0);}OSTCBPrioTbl[prio] = OS_TCB_RESERVED;              /* Reserve the table entry                  */}pevent = OSEventFreeList;                              /* Get next free event control block        */if (pevent == (OS_EVENT *)0)                           /* See if an ECB was available              */{if (prio != OS_PRIO_MUTEX_CEIL_DIS){OSTCBPrioTbl[prio] = (OS_TCB *)0;              /* No, Release the table entry              */}OS_EXIT_CRITICAL();*perr = OS_ERR_PEVENT_NULL;                         /* No more event control blocks             */return (pevent);}OSEventFreeList     = (OS_EVENT *)OSEventFreeList->OSEventPtr; /* Adjust the free list             */OS_EXIT_CRITICAL();pevent->OSEventType = OS_EVENT_TYPE_MUTEX;pevent->OSEventCnt  = (INT16U) ((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE; /* Resource is avail.     */pevent->OSEventPtr  = (void *)0;                       /* No task owning the mutex                 */
#if OS_EVENT_NAME_EN > 0upevent->OSEventName = (INT8U *) (void *)"?";
#endifOS_EventWaitListInit (pevent);*perr = OS_ERR_NONE;return (pevent);
}

互斥信号量删除

#if OS_MUTEX_DEL_EN > 0u
OS_EVENT  *OSMutexDel (OS_EVENT  *pevent,INT8U      opt,INT8U     *perr)
{BOOLEAN    tasks_waiting;OS_EVENT  *pevent_return;INT8U      pcp;                                        /* Priority ceiling priority                */INT8U      prio;OS_TCB    *ptcb;
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0){OS_SAFETY_CRITICAL_EXCEPTION();return ((OS_EVENT *)0);}#endif
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0)                           /* Validate 'pevent'                        */{*perr = OS_ERR_PEVENT_NULL;return (pevent);}#endifif (pevent->OSEventType != OS_EVENT_TYPE_MUTEX)        /* Validate event block type                */{*perr = OS_ERR_EVENT_TYPE;return (pevent);}if (OSIntNesting > 0u)                                 /* See if called from ISR ...               */{*perr = OS_ERR_DEL_ISR;                             /* ... can't DELETE from an ISR             */return (pevent);}OS_ENTER_CRITICAL();if (pevent->OSEventGrp != 0u)                          /* See if any tasks waiting on mutex        */{tasks_waiting = OS_TRUE;                           /* Yes                                      */}else{tasks_waiting = OS_FALSE;                          /* No                                       */}switch (opt){case OS_DEL_NO_PEND:                               /* DELETE MUTEX ONLY IF NO TASK WAITING --- */if (tasks_waiting == OS_FALSE){
#if OS_EVENT_NAME_EN > 0upevent->OSEventName   = (INT8U *) (void *)"?";
#endifpcp                   = (INT8U) (pevent->OSEventCnt >> 8u);if (pcp != OS_PRIO_MUTEX_CEIL_DIS){OSTCBPrioTbl[pcp] = (OS_TCB *)0;      /* Free up the PCP                          */}pevent->OSEventType   = OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr    = OSEventFreeList;  /* Return Event Control Block to free list  */pevent->OSEventCnt    = 0u;OSEventFreeList       = pevent;OS_EXIT_CRITICAL();*perr                 = OS_ERR_NONE;pevent_return         = (OS_EVENT *)0;    /* Mutex has been deleted                   */}else{OS_EXIT_CRITICAL();*perr                 = OS_ERR_TASK_WAITING;pevent_return         = pevent;}break;case OS_DEL_ALWAYS:                                /* ALWAYS DELETE THE MUTEX ---------------- */pcp  = (INT8U) (pevent->OSEventCnt >> 8u);                      /* Get PCP of mutex       */if (pcp != OS_PRIO_MUTEX_CEIL_DIS){prio = (INT8U) (pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's orig prio  */ptcb = (OS_TCB *)pevent->OSEventPtr;if (ptcb != (OS_TCB *)0)                  /* See if any task owns the mutex           */{if (ptcb->OSTCBPrio == pcp)           /* See if original prio was changed         */{OSMutex_RdyAtPrio (ptcb, prio);   /* Yes, Restore the task's original prio    */}}}while (pevent->OSEventGrp != 0u)              /* Ready ALL tasks waiting for mutex        */{(void)OS_EventTaskRdy (pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_ABORT);}#if OS_EVENT_NAME_EN > 0upevent->OSEventName   = (INT8U *) (void *)"?";
#endifpcp                   = (INT8U) (pevent->OSEventCnt >> 8u);if (pcp != OS_PRIO_MUTEX_CEIL_DIS){OSTCBPrioTbl[pcp] = (OS_TCB *)0;          /* Free up the PCP                          */}pevent->OSEventType   = OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr    = OSEventFreeList;      /* Return Event Control Block to free list  */pevent->OSEventCnt    = 0u;OSEventFreeList       = pevent;               /* Get next free event control block        */OS_EXIT_CRITICAL();if (tasks_waiting == OS_TRUE)                 /* Reschedule only if task(s) were waiting  */{OS_Sched();                               /* Find highest priority task ready to run  */}*perr         = OS_ERR_NONE;pevent_return = (OS_EVENT *)0;                /* Mutex has been deleted                   */break;default:OS_EXIT_CRITICAL();*perr         = OS_ERR_INVALID_OPT;pevent_return = pevent;break;}return (pevent_return);
}
#endif

互斥信号量获取/等待

void  OSMutexPend (OS_EVENT  *pevent,INT32U     timeout,INT8U     *perr)
{INT8U      pcp;                                        /* Priority Ceiling Priority (PCP)          */INT8U      mprio;                                      /* Mutex owner priority                     */BOOLEAN    rdy;                                        /* Flag indicating task was ready           */OS_TCB    *ptcb;OS_EVENT  *pevent2;INT8U      y;
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */OS_CPU_SR  cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0){OS_SAFETY_CRITICAL_EXCEPTION();return;}#endif
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0)                           /* Validate 'pevent'                        */{*perr = OS_ERR_PEVENT_NULL;return;}#endifif (pevent->OSEventType != OS_EVENT_TYPE_MUTEX)        /* Validate event block type                */{*perr = OS_ERR_EVENT_TYPE;return;}if (OSIntNesting > 0u)                                 /* See if called from ISR ...               */{*perr = OS_ERR_PEND_ISR;                           /* ... can't PEND from an ISR               */return;}if (OSLockNesting > 0u)                                /* See if called with scheduler locked ...  */{*perr = OS_ERR_PEND_LOCKED;                        /* ... can't PEND when locked               */return;}/*$PAGE*/OS_ENTER_CRITICAL();pcp = (INT8U) (pevent->OSEventCnt >> 8u);              /* Get PCP from mutex                       *//* Is Mutex available?                      */if ((INT8U) (pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE){pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;       /* Yes, Acquire the resource                */pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;         /*      Save priority of owning task        */pevent->OSEventPtr  = (void *)OSTCBCur;            /*      Point to owning task's OS_TCB       */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;}if (pcp != OS_PRIO_MUTEX_CEIL_DIS){mprio = (INT8U) (pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /*  Get priority of mutex owner   */ptcb  = (OS_TCB *) (pevent->OSEventPtr);                  /*     Point to TCB of mutex owner   */if (ptcb->OSTCBPrio > pcp)                                /*     Need to promote prio of owner?*/{if (mprio > OSTCBCur->OSTCBPrio){y = ptcb->OSTCBY;if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0u)        /*     See if mutex owner is ready   */{OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;     /*     Yes, Remove owner from Rdy ...*/if (OSRdyTbl[y] == 0u)                        /*          ... list at current prio */{OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;}rdy = OS_TRUE;}else{pevent2 = ptcb->OSTCBEventPtr;if (pevent2 != (OS_EVENT *)0)                 /* Remove from event wait list       */{y = ptcb->OSTCBY;pevent2->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX;if (pevent2->OSEventTbl[y] == 0u){pevent2->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY;}}rdy = OS_FALSE;                        /* No                                       */}ptcb->OSTCBPrio = pcp;                     /* Change owner task prio to PCP            */
#if OS_LOWEST_PRIO <= 63uptcb->OSTCBY    = (INT8U) ( ptcb->OSTCBPrio >> 3u);ptcb->OSTCBX    = (INT8U) ( ptcb->OSTCBPrio & 0x07u);
#elseptcb->OSTCBY    = (INT8U) ((INT8U) (ptcb->OSTCBPrio >> 4u) & 0xFFu);ptcb->OSTCBX    = (INT8U) ( ptcb->OSTCBPrio & 0x0Fu);
#endifptcb->OSTCBBitY = (OS_PRIO) (1uL << ptcb->OSTCBY);ptcb->OSTCBBitX = (OS_PRIO) (1uL << ptcb->OSTCBX);if (rdy == OS_TRUE)                        /* If task was ready at owner's priority ...*/{OSRdyGrp               |= ptcb->OSTCBBitY; /* ... make it ready at new priority.   */OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;}else{pevent2 = ptcb->OSTCBEventPtr;if (pevent2 != (OS_EVENT *)0)          /* Add to event wait list                   */{pevent2->OSEventGrp               |= ptcb->OSTCBBitY;pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;}}OSTCBPrioTbl[pcp] = ptcb;}}}OSTCBCur->OSTCBStat     |= OS_STAT_MUTEX;         /* Mutex not available, pend current task        */OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;OSTCBCur->OSTCBDly       = timeout;               /* Store timeout in current task's TCB           */OS_EventTaskWait (pevent);                        /* Suspend task until event or timeout occurs    */OS_EXIT_CRITICAL();OS_Sched();                                       /* Find next highest priority task ready         */OS_ENTER_CRITICAL();switch (OSTCBCur->OSTCBStatPend)                  /* See if we timed-out or aborted                */{case OS_STAT_PEND_OK:*perr = OS_ERR_NONE;break;case OS_STAT_PEND_ABORT:*perr = OS_ERR_PEND_ABORT;               /* Indicate that we aborted getting mutex        */break;case OS_STAT_PEND_TO:default:OS_EventTaskRemove (OSTCBCur, pevent);*perr = OS_ERR_TIMEOUT;                  /* Indicate that we didn't get mutex within TO   */break;}OSTCBCur->OSTCBStat          =  OS_STAT_RDY;      /* Set   task  status to ready                   */OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;  /* Clear pend  status                            */OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;    /* Clear event pointers                          */
#if (OS_EVENT_MULTI_EN > 0u)OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endifOS_EXIT_CRITICAL();
}

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

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

相关文章

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版本的也得卸载…

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

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

安装virt-manger虚拟机管理器

环境&#xff1a; redhat7:192.168.1.130 安装步骤&#xff1a; 安装qemu-kvm yum install -y qemu-kvm安装libvirt yum install -y libvirt重启libvirt systemctl restart libvirtd查看libvirt的版本信息 virsh version安装virt-manager yum install -y virt-manager检验…

jQuery 【关于jQuery 、 jQuery简介、基础选择器、属性选择器、jQuery扩展】(一)-全面详解(学习总结---从入门到深化)

目录 关于jQuery jQuery简介 选择器之基础选择器(一) 选择器之基础选择器(二) 选择器之属性选择器(一) 选择器之属性选择器(二) 选择器之jQuery扩展(一) 选择器之jQuery扩展(二) 关于jQuery 现在是否还需要学习jQuery&#xff0c;毫无疑问到目前为止&#xff0c;我们仍然…

exsi的安装和配置

直接虚拟真实机 vcent server 管理大量的exsi SXI原生架构模式的虚拟化技术&#xff0c;是不需要宿主操作系统的&#xff0c;它自己本身就是操作系统。因此&#xff0c;装ESXI的时候就等同于装操作系统&#xff0c;直接拿iso映像(光盘)装ESXI就可以了。 VMware vCente…

【Python 千题 —— 基础篇】欢迎光临

题目描述 题目描述 欢迎光临。为列表中的每个嘉宾打印欢迎光临语句。例如&#xff0c;有一份嘉宾列表 ["李二狗", "王子鸣"]&#xff0c;则需要根据嘉宾名单打印输出&#xff1a; 欢迎光临&#xff01;李二狗。 欢迎光临&#xff01;王子鸣。下面是一份…

IOS上架流程

准备 开发者账号完工的项目 上架步骤 一、创建App ID二、创建证书请求文件 &#xff08;CSR文件&#xff09;三、创建发布证书 &#xff08;CER&#xff09;四、创建Provisioning Profiles配置文件 &#xff08;PP文件&#xff09;五、在App Store创建应用六、打包上架 一、…

未来之路:大模型技术在自动驾驶的应用与影响

本文深入分析了大模型技术在自动驾驶领域的应用和影响&#xff0c;万字长文&#xff0c;慢慢观看~ 文中首先概述了大模型技术的发展历程&#xff0c;自动驾驶模型的迭代路径&#xff0c;以及大模型在自动驾驶行业中的作用。接着&#xff0c;详细介绍了大模型的基本定义、基础功…

基于flask+bootstrap4实现的注重创作的轻博客系统项目源码

一个注重创作的轻博客系统 作为一名技术人员一定要有自己的博客&#xff0c;用来记录平时技术上遇到的问题&#xff0c;把技术分享出去就像滚雪球一样会越來越大&#xff0c;于是我在何三博客的基础上开发了[l4blog]&#xff0c;一个使用python开发的轻量博客系统&#xff0c;…

旺店通·企业版对接打通金蝶云星空查询调拨单接口与分布式调入单新增接口

旺店通企业版对接打通金蝶云星空查询调拨单接口与分布式调入单新增接口 源系统:旺店通企业版 旺店通是北京掌上先机网络科技有限公司旗下品牌&#xff0c;国内的零售云服务提供商&#xff0c;基于云计算SaaS服务模式&#xff0c;以体系化解决方案&#xff0c;助力零售企业数字化…

分布式搜索引擎ES

文章目录 初识elasticsearch了解ES倒排索引正向索引倒排索引正向和倒排 es的一些概念文档和字段索引和映射mysql与elasticsearch 安装ES部署kibana安装IK分词器扩展词词典停用词词典 索引库操作mapping映射属性索引库的CRUD创建索引库和映射查询索引库修改索引库删除索引库 文档…

绘图软件 OmniGraffle mac中文版特点说明

OmniGraffle mac是一款图形绘制和图表设计软件&#xff0c;主要面向 macOS 和 iOS 平台。它适用于用户创建流程图、组织结构图、原型设计、网站线框图、地图等各种类型的图形。该软件的界面直观&#xff0c;用户友好&#xff0c;让用户能够轻松地创建和编辑复杂的图形。 OmniGr…

快照snapshot要点记录

目录 COW快照ROW快照 snapshot&#xff1a;快照 快照分为&#xff1a;COW快照、ROW快照 COW&#xff1a;Copy On Write 指写前复制技术 ROW&#xff1a;Redirect On Write 指写时重定向技术 COW快照 性能无法达到最高&#xff0c;因为每次都要与COW共享映射表进行比对。存储中…

13. 高精度延时

13. 高精度延时 GPT 定时器简介GPT 定时器结构GPT 定时器工作模式 GPT 定时器相关寄存器GPTx_CRGPTx_PRGPTx_SRGPTx_CNTGPTx_OCR GPT 配置步骤程序编写bsp_delay.hbsp_delay.cmain GPT 定时器简介 GPT 定时器是一个 32 位向上定时器&#xff0c;也就是从0x00000000 开始向上递…

uni-app的下拉搜索选择组合框

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家介绍uni-app中一款可以搜索下拉选择输入框的插件 下拉搜索选择组合框 superwei-combox 组合框 uni-app中可下拉搜索选…

【86 backtrader实现crypto交易策略】backtrader和ccxt对接实现中低频自动化交易-01

最近有点空闲,尝试把backtrader和一些实盘交易的接口对接一下,方便大家进行中低频交易,主要目标包括:股票(qmt),期货(ctpbee), crypto(ccxt),外盘交易(ib,已实现,但是版本比较旧,后期会继续更新). 这个周末尝试实现了backtrader和ccxt的对接,主要是参考了下面的开源代…

工具及方法 - 手机扫条码工具: SCANDIT APP

一般扫个链接使用微信扫一扫即可。扫具体条码&#xff0c;可以在微信里搜索小程序&#xff0c;打开也能扫&#xff0c;得到条码内容。 还有其他方式&#xff0c;比如使用淘宝、百度等APP也可以直接扫码条码&#xff0c;还能得到更多的信息。 使用百度的话&#xff0c;不扫条码…

springboot+maven多环境动态配置,以及编译失败的解决方案

一、前言 在我们的项目开发过程中一般会有多套的环境&#xff0c;比如比较常见的会有三套&#xff1a; dev &#xff08;研发环境&#xff09;&#xff0c;test(测试环境)&#xff0c;prod&#xff08;生产环境&#xff09;。 application.yml 是主配置文件&#xff0c;当在不…

创建具有负载平衡和集群的可扩展 Node.js 应用程序

创建具有负载平衡和集群的可扩展 Node.js 应用程序 负载平衡是提高应用程序性能、可扩展性和可用性的一项重要技术。当客户端向负载均衡器发出请求时&#xff0c;负载均衡器根据预定义的规则将请求分发到不同的实例。 可以使用cluster集群模块或 PM2 等工具根据负载均衡器的流…

数字媒体技术基础之:常见图片文件格式

在数字图像处理和图形设计领域&#xff0c;了解不同的图片文件格式及其特点是至关重要的。每种格式都有其独特的用途和优势。以下介绍一些最常见的图片文件格式。 JPEG Joint Photographic Experts Group 扩展名&#xff1a;.jpg 或 .jpeg 特点&#xff1a; 1、有损压缩&#x…