@ -214,13 +214,22 @@ PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseTyp
PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U ;
PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U ;
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY ;
PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY ;
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE ;
PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE ;
PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE ;
PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U ;
PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U ;
PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE ;
PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE ;
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0 ;
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0 ;
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U ;
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U ;
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY ;
PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY ;
/* Context switches are held pending while the scheduler is suspended. Also,
interrupts must not manipulate the xStateListItem of a TCB , or any of the
lists the xStateListItem can be referenced from , if the scheduler is suspended .
If an interrupt needs to unblock a task while the scheduler is suspended then it
moves the task ' s event list item into the xPendingReadyList , ready for the
kernel to move the task from the pending ready list into the real ready list
when the scheduler is unsuspended . The pending ready list itself can only be
accessed from a critical section . */
PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE ;
# if ( configGENERATE_RUN_TIME_STATS == 1 )
# if ( configGENERATE_RUN_TIME_STATS == 1 )
PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL ; /*< Holds the value of a timer/counter the last time a task was switched in. */
PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL ; /*< Holds the value of a timer/counter the last time a task was switched in. */
@ -393,6 +402,13 @@ to its original value when it is released. */
*/
*/
static void prvInitialiseTCBVariables ( TCB_t * const pxTCB , const char * const pcName , UBaseType_t uxPriority , const MemoryRegion_t * const xRegions , const uint16_t usStackDepth ) PRIVILEGED_FUNCTION ; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
static void prvInitialiseTCBVariables ( TCB_t * const pxTCB , const char * const pcName , UBaseType_t uxPriority , const MemoryRegion_t * const xRegions , const uint16_t usStackDepth ) PRIVILEGED_FUNCTION ; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/**
* Utility task that simply returns pdTRUE if the task referenced by xTask is
* currently in the Suspended state , or pdFALSE if the task referenced by xTask
* is in any other state .
*/
static BaseType_t prvTaskIsTaskSuspended ( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION ;
/*
/*
* Utility to ready all the lists used by the scheduler . This is called
* Utility to ready all the lists used by the scheduler . This is called
* automatically upon the creation of the first task .
* automatically upon the creation of the first task .
@ -806,9 +822,8 @@ TCB_t * pxNewTCB;
{
{
traceTASK_DELAY_UNTIL ( ) ;
traceTASK_DELAY_UNTIL ( ) ;
/* We must remove ourselves from the ready list before adding
/* Remove the task from the ready list before adding it to the
ourselves to the blocked list as the same list item is used for
blocked list as the same list item is used for both lists . */
both lists . */
if ( uxListRemove ( & ( pxCurrentTCB - > xGenericListItem ) ) = = ( UBaseType_t ) 0 )
if ( uxListRemove ( & ( pxCurrentTCB - > xGenericListItem ) ) = = ( UBaseType_t ) 0 )
{
{
/* The current task must be in a ready list, so there is
/* The current task must be in a ready list, so there is
@ -1254,25 +1269,25 @@ TCB_t * pxNewTCB;
# if ( INCLUDE_vTaskSuspend == 1 )
# if ( INCLUDE_vTaskSuspend == 1 )
BaseType_t x TaskIsTaskSuspended( const TaskHandle_t xTask )
static BaseType_t prv TaskIsTaskSuspended( const TaskHandle_t xTask )
{
{
BaseType_t xReturn = pdFALSE ;
BaseType_t xReturn = pdFALSE ;
const TCB_t * const pxTCB = ( TCB_t * ) xTask ;
const TCB_t * const pxTCB = ( TCB_t * ) xTask ;
/* Accesses xPendingReadyList so must be called from a critical
section . */
/* It does not make sense to check if the calling task is suspended. */
/* It does not make sense to check if the calling task is suspended. */
configASSERT ( xTask ) ;
configASSERT ( xTask ) ;
/* Is the task we are attempting to resume actually in the
/* Is the task being resumed actually in the suspended list? */
suspended list ? */
if ( listIS_CONTAINED_WITHIN ( & xSuspendedTaskList , & ( pxTCB - > xGenericListItem ) ) ! = pdFALSE )
if ( listIS_CONTAINED_WITHIN ( & xSuspendedTaskList , & ( pxTCB - > xGenericListItem ) ) ! = pdFALSE )
{
{
/* Has the task already been resumed from within an ISR? */
/* Has the task already been resumed from within an ISR? */
if ( listIS_CONTAINED_WITHIN ( & xPendingReadyList , & ( pxTCB - > xEventListItem ) ) = = pdFALSE )
if ( listIS_CONTAINED_WITHIN ( & xPendingReadyList , & ( pxTCB - > xEventListItem ) ) = = pdFALSE )
{
{
/* Is it in the suspended list because it is in the
/* Is it in the suspended list because it is in the Suspended
Suspended state ? It is possible to be in the suspended
state , or because is is blocked with no timeout ? */
list because it is blocked on a task with no timeout
specified . */
if ( listIS_CONTAINED_WITHIN ( NULL , & ( pxTCB - > xEventListItem ) ) ! = pdFALSE )
if ( listIS_CONTAINED_WITHIN ( NULL , & ( pxTCB - > xEventListItem ) ) ! = pdFALSE )
{
{
xReturn = pdTRUE ;
xReturn = pdTRUE ;
@ -1313,7 +1328,7 @@ TCB_t * pxNewTCB;
{
{
taskENTER_CRITICAL ( ) ;
taskENTER_CRITICAL ( ) ;
{
{
if ( x TaskIsTaskSuspended( pxTCB ) = = pdTRUE )
if ( prv TaskIsTaskSuspended( pxTCB ) = = pdTRUE )
{
{
traceTASK_RESUME ( pxTCB ) ;
traceTASK_RESUME ( pxTCB ) ;
@ -1382,12 +1397,15 @@ TCB_t * pxNewTCB;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR ( ) ;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR ( ) ;
{
{
if ( x TaskIsTaskSuspended( pxTCB ) = = pdTRUE )
if ( prv TaskIsTaskSuspended( pxTCB ) = = pdTRUE )
{
{
traceTASK_RESUME_FROM_ISR ( pxTCB ) ;
traceTASK_RESUME_FROM_ISR ( pxTCB ) ;
/* Check the ready lists can be accessed. */
if ( uxSchedulerSuspended = = ( UBaseType_t ) pdFALSE )
if ( uxSchedulerSuspended = = ( UBaseType_t ) pdFALSE )
{
{
/* Ready lists can be accessed so move the task from the
suspended list to the ready list directly . */
if ( pxTCB - > uxPriority > = pxCurrentTCB - > uxPriority )
if ( pxTCB - > uxPriority > = pxCurrentTCB - > uxPriority )
{
{
xYieldRequired = pdTRUE ;
xYieldRequired = pdTRUE ;
@ -1402,9 +1420,9 @@ TCB_t * pxNewTCB;
}
}
else
else
{
{
/* We cannot access the delayed or ready lists, so will hold this
/* The delayed or ready lists cannot be accessed so the task
task pending until the scheduler is resumed , at which point a
is held in the pending ready list until the scheduler is
yield will be performed if necessary . */
unsuspended . */
vListInsertEnd ( & ( xPendingReadyList ) , & ( pxTCB - > xEventListItem ) ) ;
vListInsertEnd ( & ( xPendingReadyList ) , & ( pxTCB - > xEventListItem ) ) ;
}
}
}
}
@ -2144,17 +2162,18 @@ TickType_t xTimeToWake;
configASSERT ( pxEventList ) ;
configASSERT ( pxEventList ) ;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED . */
SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED . */
/* Place the event list item of the TCB in the appropriate event list.
/* Place the event list item of the TCB in the appropriate event list.
This is placed in the list in priority order so the highest priority task
This is placed in the list in priority order so the highest priority task
is the first to be woken by the event . */
is the first to be woken by the event . The queue that contains the event
list is locked , preventing simultaneous access from interrupts . */
vListInsert ( pxEventList , & ( pxCurrentTCB - > xEventListItem ) ) ;
vListInsert ( pxEventList , & ( pxCurrentTCB - > xEventListItem ) ) ;
/* We must remove ourselves from the ready list before adding ourselves
/* The task must be removed from from the ready list before it is added to
t o t he blocked list as the same list item is used for both lists . We ha ve
t he blocked list as the same list item is used for both lists . Exclusi ve
exclusive access to the ready lists as the scheduler is locked . */
access to the ready lists gu aranteed becau se the scheduler is locked . */
if ( uxListRemove ( & ( pxCurrentTCB - > xGenericListItem ) ) = = ( UBaseType_t ) 0 )
if ( uxListRemove ( & ( pxCurrentTCB - > xGenericListItem ) ) = = ( UBaseType_t ) 0 )
{
{
/* The current task must be in a ready list, so there is no need to
/* The current task must be in a ready list, so there is no need to
@ -2170,15 +2189,16 @@ TickType_t xTimeToWake;
{
{
if ( xTicksToWait = = portMAX_DELAY )
if ( xTicksToWait = = portMAX_DELAY )
{
{
/* Add ourselves to the suspended task list instead of a delayed task
/* Add the task to the suspended task list instead of a delayed task
list to ensure we are not woken by a timing event . We will block
list to ensure the task is not woken by a timing event . It will
indefinitely. */
block indefinitely. */
vListInsertEnd ( & xSuspendedTaskList , & ( pxCurrentTCB - > xGenericListItem ) ) ;
vListInsertEnd ( & xSuspendedTaskList , & ( pxCurrentTCB - > xGenericListItem ) ) ;
}
}
else
else
{
{
/* Calculate the time at which the task should be woken if the event does
/* Calculate the time at which the task should be woken if the event
not occur . This may overflow but this doesn ' t matter . */
does not occur . This may overflow but this doesn ' t matter , the
scheduler will handle it . */
xTimeToWake = xTickCount + xTicksToWait ;
xTimeToWake = xTickCount + xTicksToWait ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
}
}
@ -2186,7 +2206,8 @@ TickType_t xTimeToWake;
# else /* INCLUDE_vTaskSuspend */
# else /* INCLUDE_vTaskSuspend */
{
{
/* Calculate the time at which the task should be woken if the event does
/* Calculate the time at which the task should be woken if the event does
not occur . This may overflow but this doesn ' t matter . */
not occur . This may overflow but this doesn ' t matter , the scheduler
will handle it . */
xTimeToWake = xTickCount + xTicksToWait ;
xTimeToWake = xTickCount + xTicksToWait ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
}
}
@ -2200,14 +2221,20 @@ TickType_t xTimeToWake;
configASSERT ( pxEventList ) ;
configASSERT ( pxEventList ) ;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
SCHEDULER SUSPENDED . */
the event groups implementation . */
configASSERT ( uxSchedulerSuspended ! = 0 ) ;
/* Store the item value in the event list item. */
/* Store the item value in the event list item. It is safe to access the
event list item here as interrupts won ' t access the event list item of a
task that is not in the Blocked state . */
listSET_LIST_ITEM_VALUE ( & ( pxCurrentTCB - > xEventListItem ) , xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ) ;
listSET_LIST_ITEM_VALUE ( & ( pxCurrentTCB - > xEventListItem ) , xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ) ;
/* Place the event list item of the TCB at the end of the appropriate event
/* Place the event list item of the TCB at the end of the appropriate event
list . */
list . It is safe to access the event list here because it is part of an
event group implementation - and interrupts don ' t access event groups
directly ( instead they access them indirectly by pending function calls to
the task level ) . */
vListInsertEnd ( pxEventList , & ( pxCurrentTCB - > xEventListItem ) ) ;
vListInsertEnd ( pxEventList , & ( pxCurrentTCB - > xEventListItem ) ) ;
/* The task must be removed from the ready list before it is added to the
/* The task must be removed from the ready list before it is added to the
@ -2235,8 +2262,9 @@ TickType_t xTimeToWake;
}
}
else
else
{
{
/* Calculate the time at which the task should be woken if the event does
/* Calculate the time at which the task should be woken if the event
not occur . This may overflow but this doesn ' t matter . */
does not occur . This may overflow but this doesn ' t matter , the
kernel will manage it correctly . */
xTimeToWake = xTickCount + xTicksToWait ;
xTimeToWake = xTickCount + xTicksToWait ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
}
}
@ -2244,7 +2272,8 @@ TickType_t xTimeToWake;
# else /* INCLUDE_vTaskSuspend */
# else /* INCLUDE_vTaskSuspend */
{
{
/* Calculate the time at which the task should be woken if the event does
/* Calculate the time at which the task should be woken if the event does
not occur . This may overflow but this doesn ' t matter . */
not occur . This may overflow but this doesn ' t matter , the kernel
will manage it correctly . */
xTimeToWake = xTickCount + xTicksToWait ;
xTimeToWake = xTickCount + xTicksToWait ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
prvAddCurrentTaskToDelayedList ( xTimeToWake ) ;
}
}
@ -2302,16 +2331,16 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
TCB_t * pxUnblockedTCB ;
TCB_t * pxUnblockedTCB ;
BaseType_t xReturn ;
BaseType_t xReturn ;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
/* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
SCHEDULER SUSPENDED . It can also be called from within an ISR . */
called from a critical section within an ISR . */
/* The event list is sorted in priority order, so we can remove the
/* The event list is sorted in priority order, so the first in the list can
first in the list , remove the TCB from the delayed list , and add
be removed as it is known to be the highest priority . Remove the TCB from
it to the ready list .
the delayed list , and add it to the ready list .
If an event is for a queue that is locked then this function will never
If an event is for a queue that is locked then this function will never
get called - the lock count on the queue will get modified instead . This
get called - the lock count on the queue will get modified instead . This
means we can always expect exclusive access to the event list here .
means exclusive access to the event list is guaranteed here .
This function assumes that a check has already been made to ensure that
This function assumes that a check has already been made to ensure that
pxEventList is not empty . */
pxEventList is not empty . */
@ -2333,10 +2362,9 @@ BaseType_t xReturn;
if ( pxUnblockedTCB - > uxPriority > pxCurrentTCB - > uxPriority )
if ( pxUnblockedTCB - > uxPriority > pxCurrentTCB - > uxPriority )
{
{
/* Return true if the task removed from the event list has
/* Return true if the task removed from the event list has a higher
a higher priority than the calling task . This allows
priority than the calling task . This allows the calling task to know if
the calling task to know if it should force a context
it should force a context switch now . */
switch now . */
xReturn = pdTRUE ;
xReturn = pdTRUE ;
/* Mark that a yield is pending in case the user is not using the
/* Mark that a yield is pending in case the user is not using the
@ -2357,29 +2385,24 @@ BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, cons
TCB_t * pxUnblockedTCB ;
TCB_t * pxUnblockedTCB ;
BaseType_t xReturn ;
BaseType_t xReturn ;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
SCHEDULER SUSPENDED . It can also be called from within an ISR . */
the event flags implementation . */
configASSERT ( uxSchedulerSuspended ! = pdFALSE ) ;
/* Store the new item value in the event list. */
/* Store the new item value in the event list. */
listSET_LIST_ITEM_VALUE ( pxEventListItem , xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ) ;
listSET_LIST_ITEM_VALUE ( pxEventListItem , xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ) ;
/* Remove the TCB from the delayed list, and add it to the ready list. */
/* Remove the event list form the event flag. Interrupts do not access
event flags . */
pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER ( pxEventListItem ) ;
pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER ( pxEventListItem ) ;
configASSERT ( pxUnblockedTCB ) ;
configASSERT ( pxUnblockedTCB ) ;
( void ) uxListRemove ( pxEventListItem ) ;
( void ) uxListRemove ( pxEventListItem ) ;
if ( uxSchedulerSuspended = = ( UBaseType_t ) pdFALSE )
/* 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
( void ) uxListRemove ( & ( pxUnblockedTCB - > xGenericListItem ) ) ;
lists . */
prvAddTaskToReadyList ( pxUnblockedTCB ) ;
( void ) uxListRemove ( & ( pxUnblockedTCB - > xGenericListItem ) ) ;
}
prvAddTaskToReadyList ( pxUnblockedTCB ) ;
else
{
/* Cannot access the delayed or ready lists, so will hold this task
pending until the scheduler is resumed . */
vListInsertEnd ( & ( xPendingReadyList ) , pxEventListItem ) ;
}
if ( pxUnblockedTCB - > uxPriority > pxCurrentTCB - > uxPriority )
if ( pxUnblockedTCB - > uxPriority > pxCurrentTCB - > uxPriority )
{
{
@ -2812,7 +2835,9 @@ static void prvCheckTasksWaitingTermination( void )
while ( uxTasksDeleted > ( UBaseType_t ) 0U )
while ( uxTasksDeleted > ( UBaseType_t ) 0U )
{
{
vTaskSuspendAll ( ) ;
vTaskSuspendAll ( ) ;
{
xListIsEmpty = listLIST_IS_EMPTY ( & xTasksWaitingTermination ) ;
xListIsEmpty = listLIST_IS_EMPTY ( & xTasksWaitingTermination ) ;
}
( void ) xTaskResumeAll ( ) ;
( void ) xTaskResumeAll ( ) ;
if ( xListIsEmpty = = pdFALSE )
if ( xListIsEmpty = = pdFALSE )
@ -2932,6 +2957,21 @@ TCB_t *pxNewTCB;
pxTaskStatusArray [ uxTask ] . eCurrentState = eState ;
pxTaskStatusArray [ uxTask ] . eCurrentState = eState ;
pxTaskStatusArray [ uxTask ] . uxCurrentPriority = pxNextTCB - > uxPriority ;
pxTaskStatusArray [ uxTask ] . uxCurrentPriority = pxNextTCB - > uxPriority ;
# if ( INCLUDE_vTaskSuspend == 1 )
{
/* If the task is in the suspended list then there is a chance
it is actually just blocked indefinitely - so really it should
be reported as being in the Blocked state . */
if ( eState = = eSuspended )
{
if ( listLIST_ITEM_CONTAINER ( & ( pxNextTCB - > xEventListItem ) ) ! = NULL )
{
pxTaskStatusArray [ uxTask ] . eCurrentState = eBlocked ;
}
}
}
# endif /* INCLUDE_vTaskSuspend */
# if ( configUSE_MUTEXES == 1 )
# if ( configUSE_MUTEXES == 1 )
{
{
pxTaskStatusArray [ uxTask ] . uxBasePriority = pxNextTCB - > uxBasePriority ;
pxTaskStatusArray [ uxTask ] . uxBasePriority = pxNextTCB - > uxBasePriority ;