首页 > 其他分享 >FreeRTOS 原理 --- 互斥锁

FreeRTOS 原理 --- 互斥锁

时间:2023-10-19 22:46:18浏览次数:31  
标签:task 优先级 FreeRTOS --- 互斥 pxTCB 线程 mutex

互斥锁相比于二值信号量,有以下特点:

1、通过优先级继承,防止优先级反转

2、只有互斥锁持有的线程可以释放互斥锁

3、FreeRTOS 提供支持递归版本的互斥锁

 

创建互斥锁

互斥锁使用的描述符是队列的描述符,不单独定义互斥锁描述符。

初始化时,指定队列的长度 pxNewQueue->uxLength 为1,指定队列消息占用大小 pxNewQueue->uxItemSize 为0,用队列所含消息的条数 pxQueue->uxMessagesWaiting 代表锁是否被占用,为1表示锁空闲,为0表示锁被占用,初始化为1

#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )

    QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
    {
    Queue_t *pxNewQueue;
    const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;

        pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
        prvInitialiseMutex( pxNewQueue );

        return pxNewQueue;
    }

成功获得锁

获取锁成功后,记录占用锁的任务描述符

                #if ( configUSE_MUTEXES == 1 )
                {
                    if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
                    {
                        /* Record the information required to implement
                        priority inheritance should it become necessary. */
                        pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }

    void *pvTaskIncrementMutexHeldCount( void )     {         /* If xSemaphoreCreateMutex() is called before any tasks have been created         then pxCurrentTCB will be NULL. */         if( pxCurrentTCB != NULL )         {             ( pxCurrentTCB->uxMutexesHeld )++;         }
        return pxCurrentTCB;     }
 

获取锁失败

获取锁失败,判断当前线程的优先级A是否大于拥有锁的线程的优先级B,如果是则把拥有锁的线程优先级提升到A

并把当前线程记录到互斥锁的链表里,用于锁被释放后可以唤醒当前线程;并把当前线程从就绪链表移到阻塞链表

                    if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
                    {
                        taskENTER_CRITICAL();
                        {
                            xInheritanceOccurred = xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder ); // 优先级继承
                        }
                        taskEXIT_CRITICAL();
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); 

释放锁

如果当前释放锁的线程不是拥有锁的线程,则断言

            /* A task can only have an inherited priority if it holds the mutex.             If the mutex is held by a task then it cannot be given from an             interrupt, and if a mutex is given by the holding task then it must             be the running state task. */             configASSERT( pxTCB == pxCurrentTCB );

如果释放锁的线程的优先级是继承高优先级线程的,恢复原本的优先级;从当前优先级的链表中删除此线程,添加到原本优先级的链表中

            if( pxTCB->uxPriority != pxTCB->uxBasePriority )
            {
                /* Only disinherit if no other mutexes are held. */
                if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
                {
                    /* A task can only have an inherited priority if it holds
                    the mutex.  If the mutex is held by a task then it cannot be
                    given from an interrupt, and if a mutex is given by the
                    holding task then it must be the running state task.  Remove
                    the holding task from the ready list. */
                    if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 ) // 从当前优先级的链表中删除此线程
                    {
                        taskRESET_READY_PRIORITY( pxTCB->uxPriority );
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }

                    /* Disinherit the priority before adding the task into the
                    new    ready list. */
                    traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
                    pxTCB->uxPriority = pxTCB->uxBasePriority; // 恢复原本的优先级

                    /* Reset the event list item value.  It cannot be in use for
                    any other purpose if this task is running, and it must be
                    running to give back the mutex. */
                    listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
                    prvAddTaskToReadyList( pxTCB ); // 添加到原本优先级的链表中

                    /* Return true to indicate that a context switch is required.
                    This is only actually required in the corner case whereby
                    multiple mutexes were held and the mutexes were given back
                    in an order different to that in which they were taken.
                    If a context switch did not occur when the first mutex was
                    returned, even if a task was waiting on it, then a context
                    switch should occur when the last mutex is returned whether
                    a task is waiting on it or not. */
                    xReturn = pdTRUE;
                }

支持递归的互斥锁

如果尝试获取锁的线程是持有锁的线程,递归计数加1,返回成功

#if( configUSE_RECURSIVE_MUTEXES == 1 )
    #define xSemaphoreTakeRecursive( xMutex, xBlockTime )    xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
#endif

    BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait )
    {
    BaseType_t xReturn;
    Queue_t * const pxMutex = ( Queue_t * ) xMutex;

        configASSERT( pxMutex );

        /* Comments regarding mutual exclusion as per those within
        xQueueGiveMutexRecursive(). */

        traceTAKE_MUTEX_RECURSIVE( pxMutex );

        if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
        {
            ( pxMutex->u.uxRecursiveCallCount )++;
            xReturn = pdPASS;
        }
        else
        {
            xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );

            /* pdPASS will only be returned if the mutex was successfully
            obtained.  The calling task may have entered the Blocked state
            before reaching here. */
            if( xReturn != pdFAIL )
            {
                ( pxMutex->u.uxRecursiveCallCount )++;
            }
            else
            {
                traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
            }
        }

        return xReturn;
    }

 

标签:task,优先级,FreeRTOS,---,互斥,pxTCB,线程,mutex
From: https://www.cnblogs.com/god-of-death/p/17775884.html

相关文章

  • 泛微E-Office json_common.php文件存在sql注入漏洞
    漏洞简介泛微e-office为企业办公提供丰富应用,覆盖常见协作场景,开箱即用。满足人事、行政、财务、销售、运营、市场等不同部门协作需求,帮助组织高效人事管理。系统json_common.php文件存在SQL注入漏洞漏洞复现fofa语法:app="泛微-EOffice"登录页面如下:POC:POST/building/......
  • SQL语句的基本使用5-多值子查询
    这个作业属于哪个课程https://edu.cnblogs.com/campus/uzz/cs3/这个作业要求在哪里https://edu.cnblogs.com/campus/uzz/cs3/homework/13074这个作业的目标SQL语句的基本使用5-多值子查询1.在student_info表中查找与“刘东阳”性别相同的所有学生的姓名、出生日......
  • 2023-2024-1 20231312 《计算机与程序设计》第四周学习总结
    作业信息这个作业属于哪个课程<班级的链接>2023-2024-1-计算机基础与程序设计|-这个作业要求在哪里<作业要求链接>2023-2024-1计算机基础与程序设计第四周作业|这个作业的目标《计算机基础概论》第4,5章《C语言程序设计》第3章|作业正文作业链接教材学......
  • 用友GPR-U8 slbmbygr SQL注入漏洞
    漏洞简介用友GRP-U8是面向政府及行政事业单位的财政管理应用。北京用友政务软件有限公司GRP-U8SQL注入漏洞。漏洞复现fofa语法:app="用友-GRP-U8"登录页面如下:POC:/u8qx/slbmbygr.jsp?gsdm=1';WAITFORDELAY'0:0:5'--sqlmap梭哈nuclei批量yaml文件id:yonyou_GRPU8_slb......
  • 用友GRP-RMIS datalist.jsp SQL注入漏洞
    漏洞描述用友GRP-RMIS系统的datalist.jsp存在sql注入漏洞漏洞复现fofa语法:app="用友-GRP-RMIS系统"系统登录页面如下:POC:POST/datalist.jspHTTP/1.1Host:xxxxUser-Agent:python-requests/2.31.0Accept-Encoding:gzip,deflateAccept:*/*Connection:closeConten......
  • 2023-10-19 第22本书《Jenkins 2.x 实践指南》
    囫囵吞枣读完的,也算听有收获的,他这里面介绍了ansible集成进jenkins感觉有点搞头。收益是:方便部署到多台服务器。明天继续研究一下把。 总体讲的还行,继续看看把。 主要是,我最近有点疲惫,没啥状态。心里乱乱的。 ......
  • 205-303 K8S API资源对象介绍03 (Job CronJob Endpoint ConfigMap Secret) 2.17-3.3
    一、水平自动扩容和缩容HPA(K8S版本>=1.23.x)HPA全称HorizontalPodAutoscaler,Pod水平自动伸缩,HPA可以基于CPU利用率replicationcontroller、deployment和replicaset中的pod数量进行自动扩缩容。pod自动缩放对象适用于无法缩放的对象,比如DaemonSetHPA由KubernetesAPI资源和控......
  • c#设计模式-行为型模式 之 解释器模式
    ......
  • 小程序技术未来发展的思考 - 更丰富的生态系统
    随着微信小程序、支付宝小程序和其他各种小程序的普及,小程序技术已经在移动应用开发领域占据了重要位置。然而,小程序的未来发展不仅仅限于便捷性和跨平台性,更丰富的生态系统将是小程序技术未来的一个重要趋势。在本文中,我们将探讨小程序技术未来的发展方向,并提供一个代码演示来展示......
  • AtCoder Regular Contest 167——B - Product of Divisors
    题目很明显,给定 所有因数的积不断除以最多能除几次。首先,很容易发现,对于每一对因子,都可以对答案得出B的贡献,设A的因子数目为n。将A进行质因数分解,PBa1,PBa2,PBa3……PBam,那么因数个数就是质因子加一的乘积。那么因子对数也就是前者一半。答案就是B乘因子对数除以二注意此处......