X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FSource%2Ftasks.c;h=5129bf981a6a4f9c4cc8d13a81e180118ef8d8c3;hb=03e994cd3c20d0c4cb101923e06c4dcd7376b132;hp=cf28a7184eaa5f879166a0a60ce21e664c9f59be;hpb=81f8cac691bacce5d762a8885ef51ac80d87b12a;p=freertos diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index cf28a7184..5129bf981 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -300,7 +300,10 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to pr responsible for resulting newlib operation. User must be familiar with newlib and must provide system-wide implementations of the necessary stubs. Be warned that (at the time of writing) the current newlib design - implements a system-wide malloc() that must be provided with locks. */ + implements a system-wide malloc() that must be provided with locks. + + See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + for additional information. */ struct _reent xNewLib_reent; #endif @@ -993,7 +996,9 @@ UBaseType_t x; #if ( configUSE_NEWLIB_REENTRANT == 1 ) { - /* Initialise this task's Newlib reent structure. */ + /* Initialise this task's Newlib reent structure. + See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + for additional information. */ _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) ); } #endif @@ -1204,6 +1209,10 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) check the xTasksWaitingTermination list. */ ++uxDeletedTasksWaitingCleanUp; + /* Call the delete hook before portPRE_TASK_DELETE_HOOK() as + portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */ + traceTASK_DELETE( pxTCB ); + /* The pre-delete hook is primarily for the Windows simulator, in which Windows specific clean up operations are performed, after which it is not possible to yield away from this task - @@ -1214,14 +1223,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) else { --uxCurrentNumberOfTasks; + traceTASK_DELETE( pxTCB ); prvDeleteTCB( pxTCB ); /* Reset the next expected unblock time in case it referred to the task that has just been deleted. */ prvResetNextTaskUnblockTime(); } - - traceTASK_DELETE( pxTCB ); } taskEXIT_CRITICAL(); @@ -2041,7 +2049,9 @@ BaseType_t xReturn; #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Switch Newlib's _impure_ptr variable to point to the _reent - structure specific to the task that will run first. */ + structure specific to the task that will run first. + See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + for additional information. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } #endif /* configUSE_NEWLIB_REENTRANT */ @@ -2616,7 +2626,7 @@ BaseType_t xYieldRequired = pdFALSE; relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */ configASSERT( uxSchedulerSuspended == 0 ); - /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occuring when + /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */ vTaskSuspendAll(); xPendedTicks += xTicksToCatchUp; @@ -2626,6 +2636,91 @@ BaseType_t xYieldRequired = pdFALSE; } /*----------------------------------------------------------*/ +#if ( INCLUDE_xTaskAbortDelay == 1 ) + + BaseType_t xTaskAbortDelayFromISR( TaskHandle_t xTask, BaseType_t * const pxHigherPriorityTaskWoken ) + { + TCB_t *pxTCB = xTask; + BaseType_t xReturn; + UBaseType_t uxSavedInterruptStatus; + + configASSERT( pxTCB ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* A task can only be prematurely removed from the Blocked state if + it is actually in the Blocked state. */ + if( eTaskGetState( xTask ) == eBlocked ) + { + xReturn = pdPASS; + + /* Remove the reference to the task from the blocked list. A higher + priority interrupt won't touch the xStateListItem because of the + critical section. */ + ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); + + /* Is the task waiting on an event also? If so remove it from + the event list too. */ + if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) + { + ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + + /* This lets the task know it was forcibly removed from the + blocked state so it should not re-evaluate its block time and + then block again. */ + pxTCB->ucDelayAborted = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Place the unblocked task into the appropriate ready list. */ + prvAddTaskToReadyList( pxTCB ); + + if( pxTCB->uxPriority > pxCurrentTCB->uxPriority ) + { + if( pxHigherPriorityTaskWoken != NULL ) + { + /* Pend the yield to be performed when the scheduler + is unsuspended. */ + *pxHigherPriorityTaskWoken = pdTRUE; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = pdFAIL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; + } + +#endif +/*----------------------------------------------------------*/ + #if ( INCLUDE_xTaskAbortDelay == 1 ) BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) @@ -2657,6 +2752,10 @@ BaseType_t xYieldRequired = pdFALSE; if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL ) { ( void ) uxListRemove( &( pxTCB->xEventListItem ) ); + + /* This lets the task know it was forcibly removed from the + blocked state so it should not re-evaluate its block time and + then block again. */ pxTCB->ucDelayAborted = pdTRUE; } else @@ -2843,6 +2942,19 @@ BaseType_t xSwitchRequired = pdFALSE; } } #endif /* configUSE_TICK_HOOK */ + + #if ( configUSE_PREEMPTION == 1 ) + { + if( xYieldPending != pdFALSE ) + { + xSwitchRequired = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_PREEMPTION */ } else { @@ -2857,19 +2969,6 @@ BaseType_t xSwitchRequired = pdFALSE; #endif } - #if ( configUSE_PREEMPTION == 1 ) - { - if( xYieldPending != pdFALSE ) - { - xSwitchRequired = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_PREEMPTION */ - return xSwitchRequired; } /*-----------------------------------------------------------*/ @@ -3049,7 +3148,9 @@ void vTaskSwitchContext( void ) #if ( configUSE_NEWLIB_REENTRANT == 1 ) { /* Switch Newlib's _impure_ptr variable to point to the _reent - structure specific to this task. */ + structure specific to this task. + See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + for additional information. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } #endif /* configUSE_NEWLIB_REENTRANT */ @@ -3216,6 +3317,20 @@ TCB_t *pxUnblockedTCB; configASSERT( pxUnblockedTCB ); ( void ) uxListRemove( pxEventListItem ); + #if( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked on a kernel object then xNextTaskUnblockTime + might be set to the blocked task's time out time. If the task is + unblocked for a reason other than a timeout xNextTaskUnblockTime is + normally left unchanged, because it is automatically reset to a new + value when the tick count equals xNextTaskUnblockTime. However if + tickless idling is used it might be more important to enter sleep mode + at the earliest possible time - so reset xNextTaskUnblockTime here to + ensure it is updated at the earliest possible time. */ + prvResetNextTaskUnblockTime(); + } + #endif + /* Remove the task from the delayed list and add it to the ready list. The scheduler is suspended so interrupts will not be accessing the ready lists. */ @@ -3496,6 +3611,8 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) const UBaseType_t uxNonApplicationTasks = 1; eSleepModeStatus eReturn = eStandardSleep; + /* This function must be called from a critical section. */ + if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 ) { /* A task was made ready while the scheduler was suspended. */ @@ -3537,6 +3654,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) { pxTCB = prvGetTCBFromHandle( xTaskToSet ); + configASSERT( pxTCB != NULL ); pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue; } } @@ -3871,7 +3989,9 @@ static void prvCheckTasksWaitingTermination( void ) 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. */ + to the task to free any memory allocated at the application level. + See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html + for additional information. */ #if ( configUSE_NEWLIB_REENTRANT == 1 ) { _reclaim_reent( &( pxTCB->xNewLib_reent ) ); @@ -5082,7 +5202,6 @@ TickType_t uxReturn; } #endif /* configUSE_TASK_NOTIFICATIONS */ - /*-----------------------------------------------------------*/ #if( configUSE_TASK_NOTIFICATIONS == 1 ) @@ -5116,6 +5235,32 @@ TickType_t uxReturn; #endif /* configUSE_TASK_NOTIFICATIONS */ /*-----------------------------------------------------------*/ +#if( configUSE_TASK_NOTIFICATIONS == 1 ) + + uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ) + { + TCB_t *pxTCB; + uint32_t ulReturn; + + /* If null is passed in here then it is the calling task that is having + its notification state cleared. */ + pxTCB = prvGetTCBFromHandle( xTask ); + + taskENTER_CRITICAL(); + { + /* Return the notification as it was before the bits were cleared, + then clear the bit mask. */ + ulReturn = pxCurrentTCB->ulNotifiedValue; + pxTCB->ulNotifiedValue &= ~ulBitsToClear; + } + taskEXIT_CRITICAL(); + + return ulReturn; + } + +#endif /* configUSE_TASK_NOTIFICATIONS */ +/*-----------------------------------------------------------*/ + #if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) uint32_t ulTaskGetIdleRunTimeCounter( void )