]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/tasks.c
Demo application related:
[freertos] / FreeRTOS / Source / tasks.c
index 06e08d3fe7df18a0579856366e7135d861d30cad..28dafd93f0e1454d512841461c4a3e831b397f0e 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
@@ -2150,11 +2151,13 @@ void vTaskSwitchContext( void )
                }\r
                #endif /* configGENERATE_RUN_TIME_STATS */\r
 \r
+               /* Check for stack overflow, if configured. */\r
                taskFIRST_CHECK_FOR_STACK_OVERFLOW();\r
                taskSECOND_CHECK_FOR_STACK_OVERFLOW();\r
 \r
+               /* Select a new task to run using either the generic C or port\r
+               optimised asm code. */\r
                taskSELECT_HIGHEST_PRIORITY_TASK();\r
-\r
                traceTASK_SWITCHED_IN();\r
 \r
                #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
@@ -2737,6 +2740,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 +3239,50 @@ 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
-                               {\r
-                                       taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
-                               }\r
-                               else\r
+                               /* Only disinherit if no other mutexes are held. */\r
+                               if( pxTCB->uxMutexesHeld == 0 )\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
+                                       /* Reset the event list item value.  It cannot be in use for\r
+                                       any other purpose if this task is running, and it must be\r
+                                       running to give back the mutex. */\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
+                                       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 +3293,8 @@ TCB_t *pxTCB;
                {\r
                        mtCOVERAGE_TEST_MARKER();\r
                }\r
+\r
+               return xReturn;\r
        }\r
 \r
 #endif /* configUSE_MUTEXES */\r
@@ -3294,6 +3309,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 +3584,36 @@ TickType_t uxReturn;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+void vTaskIncrementMutexHeldCount( void )\r
+{\r
+       #if ( configUSE_MUTEXES == 1 )\r
+       {\r
+               /* If xSemaphoreCreateMutex() is called before any tasks have been created\r
+               then pxCurrentTCB will be NULL. */\r
+               if( pxCurrentTCB != NULL )\r
+               {\r
+                       ( pxCurrentTCB->uxMutexesHeld )++;\r
+               }\r
+       }\r
+       #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTaskDecrementMutexHeldCount( void )\r
+{\r
+       #if ( configUSE_MUTEXES == 1 )\r
+       {\r
+               /* If xSemaphoreCreateMutex() is called before any tasks have been created\r
+               then pxCurrentTCB will be NULL. */\r
+               if( pxCurrentTCB != NULL )\r
+               {\r
+                       configASSERT( pxCurrentTCB->uxMutexesHeld );\r
+                       ( pxCurrentTCB->uxMutexesHeld )--;\r
+               }\r
+       }\r
+       #endif\r
+}\r
+\r
 #ifdef FREERTOS_MODULE_TEST\r
        #include "tasks_test_access_functions.h"\r
 #endif\r