Core kernel code changes:

+ Added xTaskAbortDelay() function, which causes a task to exit the Blocked state even before the timeout has expired or the event the task is waiting for has occurred.
+ For efficiency and code size reasons on some architectures, replace many instances of "== pdTRUE" with "!= pdFALSE".
pull/1/head
Richard Barry 9 years ago
parent 2acc8f2c99
commit c7b7b90cc9

@ -744,6 +744,31 @@ void vTaskDelay( const TickType_t xTicksToDelay ) PRIVILEGED_FUNCTION;
*/ */
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION; void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ) PRIVILEGED_FUNCTION;
/**
* task. h
* <pre>BaseType_t xTaskAbortDelay( TaskHandle_t xTask );</pre>
*
* INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this
* function to be available.
*
* A task will enter the Blocked state when it is waiting for an event. The
* event it is waiting for can be a temporal event (waiting for a time), such
* as when vTaskDelay() is called, or an event on an object, such as when
* xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task
* that is in the Blocked state is used in a call to xTaskAbortDelay() then the
* task will leave the Blocked state, and return from whichever function call
* placed the task into the Blocked state.
*
* @param xTask The handle of the task to remove from the Blocked state.
*
* @return If the task referenced by xTask was not in the Blocked state then
* pdFAIL is returned. Otherwise pdPASS is returned.
*
* \defgroup xTaskAbortDelay xTaskAbortDelay
* \ingroup TaskCtrl
*/
BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
/** /**
* task. h * task. h
* <pre>UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );</pre> * <pre>UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );</pre>

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
URL=http://www.freertos.org/a00111.html
IDList=

@ -3,11 +3,12 @@ components and are common to every port, and one or more files that are
specific to a particular microcontroller and/or compiler. specific to a particular microcontroller and/or compiler.
+ The FreeRTOS/Source/Portable/MemMang directory contains the three sample + The FreeRTOS/Source/Portable/MemMang directory contains the five sample
memory allocators as described on the http://www.FreeRTOS.org WEB site. memory allocators as described on the http://www.FreeRTOS.org WEB site.
+ The other directories each contain files specific to a particular + The other directories each contain files specific to a particular
microcontroller or compiler. microcontroller or compiler, where the directory name denotes the compiler
specific files the directory contains.

@ -303,7 +303,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
it will be possible to write to it. */ it will be possible to write to it. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{ {
queueYIELD_IF_USING_PREEMPTION(); queueYIELD_IF_USING_PREEMPTION();
} }
@ -651,7 +651,7 @@ Queue_t *pxNewQueue;
/* pdPASS will only be returned if the mutex was successfully /* pdPASS will only be returned if the mutex was successfully
obtained. The calling task may have entered the Blocked state obtained. The calling task may have entered the Blocked state
before reaching here. */ before reaching here. */
if( xReturn == pdPASS ) if( xReturn != pdFAIL )
{ {
( pxMutex->u.uxRecursiveCallCount )++; ( pxMutex->u.uxRecursiveCallCount )++;
} }
@ -732,7 +732,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{ {
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
{ {
/* The queue is a member of a queue set, and posting /* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to to the queue set caused a higher priority task to
@ -750,7 +750,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
queue then unblock it now. */ queue then unblock it now. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{ {
/* The unblocked task has a priority higher than /* The unblocked task has a priority higher than
our own so yield immediately. Yes it is ok to our own so yield immediately. Yes it is ok to
@ -783,7 +783,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
queue then unblock it now. */ queue then unblock it now. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{ {
/* The unblocked task has a priority higher than /* The unblocked task has a priority higher than
our own so yield immediately. Yes it is ok to do our own so yield immediately. Yes it is ok to do
@ -920,7 +920,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
queue then unblock it now. */ queue then unblock it now. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{ {
/* The unblocked task has a priority higher than /* The unblocked task has a priority higher than
our own so yield immediately. */ our own so yield immediately. */
@ -1031,7 +1031,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{ {
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
@ -1191,7 +1191,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{ {
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE ) if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )
{ {
/* The queue is a member of a queue set, and posting /* The queue is a member of a queue set, and posting
to the queue set caused a higher priority task to to the queue set caused a higher priority task to
@ -1352,7 +1352,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{ {
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE ) if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE )
{ {
/* The semaphore is a member of a queue set, and /* The semaphore is a member of a queue set, and
posting to the queue set caused a higher priority posting to the queue set caused a higher priority
@ -1506,7 +1506,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{ {
queueYIELD_IF_USING_PREEMPTION(); queueYIELD_IF_USING_PREEMPTION();
} }
@ -2019,7 +2019,7 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
{ {
if( pxQueue->pxQueueSetContainer != NULL ) if( pxQueue->pxQueueSetContainer != NULL )
{ {
if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE ) if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE )
{ {
/* The queue is a member of a queue set, and posting to /* The queue is a member of a queue set, and posting to
the queue set caused a higher priority task to unblock. the queue set caused a higher priority task to unblock.
@ -2033,8 +2033,9 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
} }
else else
{ {
/* Tasks that are removed from the event list will get added to /* Tasks that are removed from the event list will get
the pending ready list as the scheduler is still suspended. */ added to the pending ready list as the scheduler is still
suspended. */
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
{ {
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )

@ -199,8 +199,12 @@ typedef struct tskTaskControlBlock
volatile uint8_t ucNotifyState; volatile uint8_t ucNotifyState;
#endif #endif
#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) #if( configSUPPORT_STATIC_ALLOCATION == 1 )
uint8_t ucStaticAllocationFlags; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */ uint8_t ucStaticAllocationFlags; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */
#endif
#if( INCLUDE_xTaskAbortDelay == 1 )
uint8_t ucDelayAborted;
#endif #endif
} tskTCB; } tskTCB;
@ -210,8 +214,8 @@ below to enable the use of older kernel aware debuggers. */
typedef tskTCB TCB_t; typedef tskTCB TCB_t;
/* /*
* Some kernel aware debuggers require the data the debugger needs access to to * Some kernel aware debuggers require the data the debugger needs access to be
* be global, rather than file scope. * global, rather than file scope.
*/ */
#ifdef portREMOVE_STATIC_QUALIFIER #ifdef portREMOVE_STATIC_QUALIFIER
#define static #define static
@ -1244,7 +1248,7 @@ StackType_t *pxTopOfStack;
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
if( xYieldRequired == pdTRUE ) if( xYieldRequired != pdFALSE )
{ {
taskYIELD_IF_USING_PREEMPTION(); taskYIELD_IF_USING_PREEMPTION();
} }
@ -1415,7 +1419,7 @@ StackType_t *pxTopOfStack;
{ {
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE ) if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
{ {
traceTASK_RESUME( pxTCB ); traceTASK_RESUME( pxTCB );
@ -1484,7 +1488,7 @@ StackType_t *pxTopOfStack;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE ) if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
{ {
traceTASK_RESUME_FROM_ISR( pxTCB ); traceTASK_RESUME_FROM_ISR( pxTCB );
@ -1769,7 +1773,7 @@ BaseType_t xAlreadyYielded = pdFALSE;
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
if( xYieldPending == pdTRUE ) if( xYieldPending != pdFALSE )
{ {
#if( configUSE_PREEMPTION != 0 ) #if( configUSE_PREEMPTION != 0 )
{ {
@ -1933,6 +1937,9 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
UBaseType_t uxQueue = configMAX_PRIORITIES; UBaseType_t uxQueue = configMAX_PRIORITIES;
TCB_t* pxTCB; TCB_t* pxTCB;
/* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
vTaskSuspendAll(); vTaskSuspendAll();
{ {
/* Search the ready lists. */ /* Search the ready lists. */
@ -2094,6 +2101,80 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
#if ( INCLUDE_xTaskAbortDelay == 1 )
BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
{
TCB_t *pxTCB = ( TCB_t * ) xTask;
BaseType_t xReturn = pdFALSE;
configASSERT( pxTCB );
vTaskSuspendAll();
{
/* A task can only be prematurely removed from the Blocked state if
it is actually in the Blocked state. */
if( eTaskGetState( xTask ) == eBlocked )
{
/* Remove the reference to the task from the blocked list. An
interrupt won't touch the xGenericListItem because the
scheduler is suspended. */
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
/* Is the task waiting on an event also? If so remove it from
the event list too. Interrupts can touch the event list item,
even though the scheduler is suspended, so a critical section
is used. */
taskENTER_CRITICAL();
{
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
{
( void ) uxListRemove( &( pxTCB->xEventListItem ) );
pxTCB->ucDelayAborted = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
/* Place the unblocked task into the appropriate ready list. */
prvAddTaskToReadyList( pxTCB );
/* A task being unblocked cannot cause an immediate context
switch if preemption is turned off. */
#if ( configUSE_PREEMPTION == 1 )
{
/* Preemption is on, but a context switch should only be
performed if the unblocked task has a priority that is
equal to or higher than the currently executing task. */
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* Pend the yield to be performed when the scheduler
is unsuspended. */
xYieldPending = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* configUSE_PREEMPTION */
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
xTaskResumeAll();
return xReturn;
}
#endif /* INCLUDE_xTaskAbortDelay */
/*----------------------------------------------------------*/
BaseType_t xTaskIncrementTick( void ) BaseType_t xTaskIncrementTick( void )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
@ -2479,7 +2560,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte
/* If the task should block indefinitely then set the block time to a /* If the task should block indefinitely then set the block time to a
value that will be recognised as an indefinite delay inside the value that will be recognised as an indefinite delay inside the
prvAddCurrentTaskToDelayedList() function. */ prvAddCurrentTaskToDelayedList() function. */
if( xWaitIndefinitely == pdTRUE ) if( xWaitIndefinitely != pdFALSE )
{ {
xTicksToWait = portMAX_DELAY; xTicksToWait = portMAX_DELAY;
} }
@ -2624,15 +2705,26 @@ BaseType_t xReturn;
/* Minor optimisation. The tick count cannot change in this block. */ /* Minor optimisation. The tick count cannot change in this block. */
const TickType_t xConstTickCount = xTickCount; const TickType_t xConstTickCount = xTickCount;
#if( INCLUDE_xTaskAbortDelay == 1 )
if( pxCurrentTCB->ucDelayAborted != pdFALSE )
{
/* The delay was aborted, which is not the same as a time out,
but has the same result. */
pxCurrentTCB->ucDelayAborted = pdFALSE;
xReturn = pdTRUE;
}
else
#endif
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
/* If INCLUDE_vTaskSuspend is set to 1 and the block time specified
is the maximum block time then the task should block indefinitely,
and therefore never time out. */
if( *pxTicksToWait == portMAX_DELAY ) if( *pxTicksToWait == portMAX_DELAY )
{ {
/* If INCLUDE_vTaskSuspend is set to 1 and the block time
specified is the maximum block time then the task should block
indefinitely, and therefore never time out. */
xReturn = pdFALSE; xReturn = pdFALSE;
} }
else /* We are not blocking indefinitely, perform the checks below. */ else
#endif #endif
if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */ if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
@ -2644,7 +2736,7 @@ BaseType_t xReturn;
was called. */ was called. */
xReturn = pdTRUE; xReturn = pdTRUE;
} }
else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
{ {
/* Not a genuine timeout. Adjust parameters for time remaining. */ /* Not a genuine timeout. Adjust parameters for time remaining. */
*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering ); *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
@ -2971,6 +3063,12 @@ UBaseType_t x;
_REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) ); _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
} }
#endif #endif
#if( INCLUDE_xTaskAbortDelay == 1 )
{
pxTCB->ucDelayAborted = pdFALSE;
}
#endif
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -4499,10 +4597,19 @@ TickType_t uxReturn;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, BaseType_t xCanBlockIndefinitely ) static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
{ {
TickType_t xTimeToWake; TickType_t xTimeToWake;
#if( INCLUDE_xTaskAbortDelay == 1 )
{
/* About to enter a delayed list, so ensure the ucDelayAborted flag is
reset to pdFALSE so it can be detected as having been set to pdTRUE
when the task leaves the Blocked state. */
pxCurrentTCB->ucDelayAborted = pdFALSE;
}
#endif
/* Remove the task from the ready list before adding it to the blocked list /* Remove the task from the ready list before adding it to the blocked list
as the same list item is used for both lists. */ as the same list item is used for both lists. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 ) if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )

@ -454,7 +454,7 @@ Timer_t * const pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTi
/* The timer is inserted into a list using a time relative to anything /* The timer is inserted into a list using a time relative to anything
other than the current time. It will therefore be inserted into the other than the current time. It will therefore be inserted into the
correct list relative to the time this task thinks it is now. */ correct list relative to the time this task thinks it is now. */
if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) == pdTRUE ) if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )
{ {
/* The timer expired before it was added to the active timer /* The timer expired before it was added to the active timer
list. Reload it now. */ list. Reload it now. */
@ -730,7 +730,7 @@ TickType_t xTimeNow;
case tmrCOMMAND_RESET_FROM_ISR : case tmrCOMMAND_RESET_FROM_ISR :
case tmrCOMMAND_START_DONT_TRACE : case tmrCOMMAND_START_DONT_TRACE :
/* Start or restart a timer. */ /* Start or restart a timer. */
if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) == pdTRUE ) if( prvInsertTimerInActiveList( pxTimer, xMessage.u.xTimerParameters.xMessageValue + pxTimer->xTimerPeriodInTicks, xTimeNow, xMessage.u.xTimerParameters.xMessageValue ) != pdFALSE )
{ {
/* The timer expired before it was added to the active /* The timer expired before it was added to the active
timer list. Process it now. */ timer list. Process it now. */

Loading…
Cancel
Save