μ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.hqwc.cn/news/176284.html

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

相关文章

【Linux】Linux基础IO(下)

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;Linux &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 上一篇博客&#xff1a;【Linux】…

Element-Ui el-table 动态添加行

一、在项目需要使用 这个需求主要是在项目中需要用到 1.点击新增按钮&#xff0c;可以实现新增行。 2.在每个列里面可以进行输入。 3.可以删除新增的行&#xff0c;包括数据。 二、HTML代码 1.主要是循环每一个列&#xff0c;而且这些列都是动态&#xff0c;根据父组件传过来…

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

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

Linux常用命令——bzgrep命令

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

初识Linux:目录路径

目录 提示&#xff1a;以下指令均在Xshell 7 中进行 一、基本指令&#xff1a; 二、文件 文件内容文件属性 三、ls 指令拓展 1、 ls -l &#xff1a; 2、ls -la&#xff1a; 3、ls [目录名] &#xff1a; 4、ls -ld [目录名]&#xff1a; 四、Linux中的文件和…

IDEA-git commit log 线

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

Zephyr-7B论文解析及全量训练、Lora训练

文章目录 一、Zephyr&#xff1a;Direct Distillation of LM Alignment1.1 开发经过1.1.1 Zephyr-7B-alpha1.1.2 Zephyr-7B-beta 1.2 摘要1.3 相关工作1.4 算法1.4.1 蒸馏监督微调&#xff08;dSFT&#xff09;1.4.2 基于偏好的AI反馈 (AIF&#xff09;1.4.3 直接蒸馏偏好优化&…

大数据毕业设计选题推荐-污水处理大数据平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

Python | 机器学习之聚类算法

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《人工智能奇遇记》&#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 目录结构 1. 机器学习之聚类算法概念 1.1 机器学习 1.2 聚类算法 2. 聚类算法 2.1 实验目的…

Rust实战教程:构建您的第一个应用

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将一起动手实践&#xff0c;通过构建一个简单的Rust应用来深入理解这门语言。 我们的项目是一个命令行文本文件分析器&#xff0c;它不仅能读取和显示文件内容&#xff0c;还会提供一些基础的文本分析&#xff0c;如计算…

python 多线程池 CPU拉满

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

什么是Vue.js中的单向数据流(one-way data flow)?为什么它重要?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…