mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-12 09:07:46 -04:00
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".
This commit is contained in:
parent
2acc8f2c99
commit
c7b7b90cc9
6 changed files with 171 additions and 32 deletions
|
@ -199,8 +199,12 @@ typedef struct tskTaskControlBlock
|
|||
volatile uint8_t ucNotifyState;
|
||||
#endif
|
||||
|
||||
#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. */
|
||||
#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. */
|
||||
#endif
|
||||
|
||||
#if( INCLUDE_xTaskAbortDelay == 1 )
|
||||
uint8_t ucDelayAborted;
|
||||
#endif
|
||||
|
||||
} tskTCB;
|
||||
|
@ -210,8 +214,8 @@ below to enable the use of older kernel aware debuggers. */
|
|||
typedef tskTCB TCB_t;
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require the data the debugger needs access to to
|
||||
* be global, rather than file scope.
|
||||
* Some kernel aware debuggers require the data the debugger needs access to be
|
||||
* global, rather than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
|
@ -1244,7 +1248,7 @@ StackType_t *pxTopOfStack;
|
|||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( xYieldRequired == pdTRUE )
|
||||
if( xYieldRequired != pdFALSE )
|
||||
{
|
||||
taskYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
|
@ -1415,7 +1419,7 @@ StackType_t *pxTopOfStack;
|
|||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
|
||||
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
|
||||
{
|
||||
traceTASK_RESUME( pxTCB );
|
||||
|
||||
|
@ -1484,7 +1488,7 @@ StackType_t *pxTopOfStack;
|
|||
|
||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
|
||||
if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
|
||||
{
|
||||
traceTASK_RESUME_FROM_ISR( pxTCB );
|
||||
|
||||
|
@ -1769,7 +1773,7 @@ BaseType_t xAlreadyYielded = pdFALSE;
|
|||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( xYieldPending == pdTRUE )
|
||||
if( xYieldPending != pdFALSE )
|
||||
{
|
||||
#if( configUSE_PREEMPTION != 0 )
|
||||
{
|
||||
|
@ -1933,6 +1937,9 @@ UBaseType_t uxTaskGetNumberOfTasks( void )
|
|||
UBaseType_t uxQueue = configMAX_PRIORITIES;
|
||||
TCB_t* pxTCB;
|
||||
|
||||
/* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
|
||||
configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* 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 */
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
#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 )
|
||||
{
|
||||
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
|
||||
value that will be recognised as an indefinite delay inside the
|
||||
prvAddCurrentTaskToDelayedList() function. */
|
||||
if( xWaitIndefinitely == pdTRUE )
|
||||
if( xWaitIndefinitely != pdFALSE )
|
||||
{
|
||||
xTicksToWait = portMAX_DELAY;
|
||||
}
|
||||
|
@ -2624,15 +2705,26 @@ BaseType_t xReturn;
|
|||
/* Minor optimisation. The tick count cannot change in this block. */
|
||||
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 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 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;
|
||||
}
|
||||
else /* We are not blocking indefinitely, perform the checks below. */
|
||||
else
|
||||
#endif
|
||||
|
||||
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. */
|
||||
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. */
|
||||
*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
|
||||
|
@ -2971,6 +3063,12 @@ UBaseType_t x;
|
|||
_REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
|
||||
}
|
||||
#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;
|
||||
|
||||
#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
|
||||
as the same list item is used for both lists. */
|
||||
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue