]> git.sur5r.net Git - freertos/commitdiff
Implementation of mutex held counting in tasks.c - needs optimisation before release.
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 16 Jun 2014 12:55:50 +0000 (12:55 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 16 Jun 2014 12:55:50 +0000 (12:55 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2264 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Source/tasks.c

index 06e08d3fe7df18a0579856366e7135d861d30cad..0147ad0b07515d49cc44309e16e9e663151cb462 100644 (file)
@@ -146,6 +146,7 @@ typedef struct tskTaskControlBlock
 \r
        #if ( configUSE_MUTEXES == 1 )\r
                UBaseType_t     uxBasePriority;         /*< The priority last assigned to the task - used by the priority inheritance mechanism. */\r
+               UBaseType_t     uxMutexesHeld;\r
        #endif\r
 \r
        #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
@@ -2737,6 +2738,7 @@ UBaseType_t x;
        #if ( configUSE_MUTEXES == 1 )\r
        {\r
                pxTCB->uxBasePriority = uxPriority;\r
+               pxTCB->uxMutexesHeld = 0;\r
        }\r
        #endif /* configUSE_MUTEXES */\r
 \r
@@ -3235,41 +3237,57 @@ TCB_t *pxTCB;
 \r
 #if ( configUSE_MUTEXES == 1 )\r
 \r
-       void vTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )\r
+       BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )\r
        {\r
        TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;\r
+       BaseType_t xReturn = pdFALSE;\r
 \r
                if( pxMutexHolder != NULL )\r
                {\r
                        if( pxTCB->uxPriority != pxTCB->uxBasePriority )\r
                        {\r
-                               /* We must be the running task to be able to give the mutex back.\r
-                               Remove ourselves from the ready list we currently appear in. */\r
-                               if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
+                               /* Only disinherit if no other mutexes are held. */\r
+                               if( pxTCB->uxMutexesHeld == 0 )\r
                                {\r
-                                       taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
-                               }\r
-                               else\r
-                               {\r
-                                       mtCOVERAGE_TEST_MARKER();\r
-                               }\r
+                                       /* The holding task must be the running task to be able to give\r
+                                       the mutex back.  Remove the holding task from the ready list. */\r
+                                       if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
+                                       {\r
+                                               taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               mtCOVERAGE_TEST_MARKER();\r
+                                       }\r
 \r
-                               /* Disinherit the priority before adding the task into the new\r
-                               ready list. */\r
-                               traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );\r
-                               pxTCB->uxPriority = pxTCB->uxBasePriority;\r
+                                       /* Disinherit the priority before adding the task into the new\r
+                                       ready list. */\r
+                                       traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );\r
+                                       pxTCB->uxPriority = pxTCB->uxBasePriority;\r
 \r
-                               /* Only reset the event list item value if the value is not\r
-                               being used for anything else. */\r
-                               if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
-                               {\r
-                                       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. */\r
+                                       /* Only reset the event list item value if the value is not\r
+                                       being used for anything else. */\r
+                                       if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
+                                       {\r
+                                               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. */\r
+                                       }\r
+                                       else\r
+                                       {\r
+#warning Is it possible to come through here?\r
+                                               mtCOVERAGE_TEST_MARKER();\r
+                                       }\r
+                                       prvAddTaskToReadyList( pxTCB );\r
+\r
+                                       /* Return true to indicate that a context switch is required.\r
+                                       This is only actually required in the corner case whereby\r
+                                       multiple mutexes were held and the mutexes were given back\r
+                                       in an order different to that in which they were taken. */\r
+                                       xReturn = pdTRUE;\r
                                }\r
                                else\r
                                {\r
                                        mtCOVERAGE_TEST_MARKER();\r
                                }\r
-                               prvAddTaskToReadyList( pxTCB );\r
                        }\r
                        else\r
                        {\r
@@ -3280,6 +3298,8 @@ TCB_t *pxTCB;
                {\r
                        mtCOVERAGE_TEST_MARKER();\r
                }\r
+\r
+               return xReturn;\r
        }\r
 \r
 #endif /* configUSE_MUTEXES */\r
@@ -3294,6 +3314,18 @@ TCB_t *pxTCB;
                if( xSchedulerRunning != pdFALSE )\r
                {\r
                        ( pxCurrentTCB->uxCriticalNesting )++;\r
+\r
+                       /* This is not the interrupt safe version of the enter critical\r
+                       function so     assert() if it is being called from an interrupt\r
+                       context.  Only API functions that end in "FromISR" can be used in an\r
+                       interrupt.  Only assert if the critical nesting count is 1 to\r
+                       protect against recursive calls if the assert function also uses a\r
+                       critical section. */\r
+                       if( pxCurrentTCB->uxCriticalNesting == 1 )\r
+                       {\r
+                               portASSERT_IF_IN_ISR();\r
+                       }\r
+\r
                }\r
                else\r
                {\r
@@ -3557,6 +3589,18 @@ TickType_t uxReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+void vTaskIncrementMutexHeldCount( void )\r
+{\r
+       ( pxCurrentTCB->uxMutexesHeld )++;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTaskDecrementMutexHeldCount( void )\r
+{\r
+       configASSERT( pxCurrentTCB->uxMutexesHeld );\r
+       ( pxCurrentTCB->uxMutexesHeld )--;\r
+}\r
+\r
 #ifdef FREERTOS_MODULE_TEST\r
        #include "tasks_test_access_functions.h"\r
 #endif\r