X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FSource%2Ftasks.c;h=28dafd93f0e1454d512841461c4a3e831b397f0e;hb=857280ed8fe6610361bd144a505da7194591f2b1;hp=8512e1bbc6ed75dea716716ba54ae24f557b9409;hpb=50a6eb74698a256cb085acff88a58e439cabfbcb;p=freertos diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index 8512e1bbc..28dafd93f 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -1,5 +1,5 @@ /* - FreeRTOS V8.0.0 - Copyright (C) 2014 Real Time Engineers Ltd. + FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -24,10 +24,10 @@ the terms of the GNU General Public License (version 2) as published by the Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - >>! NOTE: The modification to the GPL is included to allow you to distribute - >>! a combined work that includes FreeRTOS without being obliged to provide - >>! the source code for proprietary components outside of the FreeRTOS - >>! kernel. + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS @@ -146,6 +146,7 @@ typedef struct tskTaskControlBlock #if ( configUSE_MUTEXES == 1 ) UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ + UBaseType_t uxMutexesHeld; #endif #if ( configUSE_APPLICATION_TASK_TAG == 1 ) @@ -760,7 +761,11 @@ TCB_t * pxNewTCB; { /* Reset the next expected unblock time in case it referred to the task that has just been deleted. */ - prvResetNextTaskUnblockTime(); + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); } } } @@ -1259,7 +1264,11 @@ TCB_t * pxNewTCB; /* A task other than the currently running task was suspended, reset the next expected unblock time in case it referred to the task that is now in the Suspended state. */ - prvResetNextTaskUnblockTime(); + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); } else { @@ -2142,11 +2151,13 @@ void vTaskSwitchContext( void ) } #endif /* configGENERATE_RUN_TIME_STATS */ + /* Check for stack overflow, if configured. */ taskFIRST_CHECK_FOR_STACK_OVERFLOW(); taskSECOND_CHECK_FOR_STACK_OVERFLOW(); + /* Select a new task to run using either the generic C or port + optimised asm code. */ taskSELECT_HIGHEST_PRIORITY_TASK(); - traceTASK_SWITCHED_IN(); #if ( configUSE_NEWLIB_REENTRANT == 1 ) @@ -2729,6 +2740,7 @@ UBaseType_t x; #if ( configUSE_MUTEXES == 1 ) { pxTCB->uxBasePriority = uxPriority; + pxTCB->uxMutexesHeld = 0; } #endif /* configUSE_MUTEXES */ @@ -3078,8 +3090,13 @@ TCB_t *pxNewTCB; want to allocate and clean RAM statically. */ portCLEAN_UP_TCB( pxTCB ); - /* Free up the memory allocated by the scheduler for the task. It is up to - the task to free any memory allocated at the application level. */ + /* Free up the memory allocated by the scheduler for the task. It is up + to the task to free any memory allocated at the application level. */ + #if ( configUSE_NEWLIB_REENTRANT == 1 ) + { + _reclaim_reent( &( pxTCB->xNewLib_reent ) ); + } + #endif /* configUSE_NEWLIB_REENTRANT */ vPortFreeAligned( pxTCB->pxStack ); vPortFree( pxTCB ); } @@ -3222,41 +3239,50 @@ TCB_t *pxTCB; #if ( configUSE_MUTEXES == 1 ) - void vTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) + BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) { TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder; + BaseType_t xReturn = pdFALSE; if( pxMutexHolder != NULL ) { if( pxTCB->uxPriority != pxTCB->uxBasePriority ) { - /* We must be the running task to be able to give the mutex back. - Remove ourselves from the ready list we currently appear in. */ - if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) - { - taskRESET_READY_PRIORITY( pxTCB->uxPriority ); - } - else + /* Only disinherit if no other mutexes are held. */ + if( pxTCB->uxMutexesHeld == 0 ) { - mtCOVERAGE_TEST_MARKER(); - } + /* The holding task must be the running task to be able to give + the mutex back. Remove the holding task from the ready list. */ + if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( 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; + /* Disinherit the priority before adding the task into the new + ready list. */ + traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority ); + pxTCB->uxPriority = pxTCB->uxBasePriority; - /* Only reset the event list item value if the value is not - being used for anything else. */ - if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL ) - { + /* 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. */ + xReturn = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } - prvAddTaskToReadyList( pxTCB ); } else { @@ -3267,6 +3293,8 @@ TCB_t *pxTCB; { mtCOVERAGE_TEST_MARKER(); } + + return xReturn; } #endif /* configUSE_MUTEXES */ @@ -3281,6 +3309,18 @@ TCB_t *pxTCB; if( xSchedulerRunning != pdFALSE ) { ( pxCurrentTCB->uxCriticalNesting )++; + + /* This is not the interrupt safe version of the enter critical + function so assert() if it is being called from an interrupt + context. Only API functions that end in "FromISR" can be used in an + interrupt. Only assert if the critical nesting count is 1 to + protect against recursive calls if the assert function also uses a + critical section. */ + if( pxCurrentTCB->uxCriticalNesting == 1 ) + { + portASSERT_IF_IN_ISR(); + } + } else { @@ -3544,6 +3584,36 @@ TickType_t uxReturn; } /*-----------------------------------------------------------*/ +void vTaskIncrementMutexHeldCount( void ) +{ + #if ( configUSE_MUTEXES == 1 ) + { + /* If xSemaphoreCreateMutex() is called before any tasks have been created + then pxCurrentTCB will be NULL. */ + if( pxCurrentTCB != NULL ) + { + ( pxCurrentTCB->uxMutexesHeld )++; + } + } + #endif +} +/*-----------------------------------------------------------*/ + +void vTaskDecrementMutexHeldCount( void ) +{ + #if ( configUSE_MUTEXES == 1 ) + { + /* If xSemaphoreCreateMutex() is called before any tasks have been created + then pxCurrentTCB will be NULL. */ + if( pxCurrentTCB != NULL ) + { + configASSERT( pxCurrentTCB->uxMutexesHeld ); + ( pxCurrentTCB->uxMutexesHeld )--; + } + } + #endif +} + #ifdef FREERTOS_MODULE_TEST #include "tasks_test_access_functions.h" #endif