Make xTaskIsTaskSuspended() a private function as it should only be called from within critical sections.

Fix issue in and simplify the xTaskRemoveFromUnorderedEventList() function.  The function is new to the V8 release candidates so does not effect official released code.
This commit is contained in:
Richard Barry 2014-02-10 17:02:37 +00:00
parent eea669240b
commit 84f4ae9aa0
6 changed files with 112 additions and 96 deletions

View File

@ -84,7 +84,6 @@ only for ports that are using the MPU. */
#define vTaskPrioritySet MPU_vTaskPrioritySet
#define eTaskGetState MPU_eTaskGetState
#define vTaskSuspend MPU_vTaskSuspend
#define xTaskIsTaskSuspended MPU_xTaskIsTaskSuspended
#define vTaskResume MPU_vTaskResume
#define vTaskSuspendAll MPU_vTaskSuspendAll
#define xTaskResumeAll MPU_xTaskResumeAll

View File

@ -173,7 +173,7 @@ typedef void * QueueSetMemberHandle_t;
* <pre>
BaseType_t xQueueSendToToFront(
QueueHandle_t xQueue,
const void * pvItemToQueue,
const void *pvItemToQueue,
TickType_t xTicksToWait
);
* </pre>

View File

@ -1028,17 +1028,6 @@ void vTaskSuspendAll( void ) PRIVILEGED_FUNCTION;
*/
BaseType_t xTaskResumeAll( void ) PRIVILEGED_FUNCTION;
/**
* task. h
* <pre>BaseType_t xTaskIsTaskSuspended( const TaskHandle_t xTask );</pre>
*
* 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.
*
*/
BaseType_t xTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------
* TASK UTILITIES
*----------------------------------------------------------*/

View File

@ -179,7 +179,6 @@ UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t pxTask );
void MPU_vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority );
eTaskState MPU_eTaskGetState( TaskHandle_t pxTask );
void MPU_vTaskSuspend( TaskHandle_t pxTaskToSuspend );
BaseType_t MPU_xTaskIsTaskSuspended( TaskHandle_t xTask );
void MPU_vTaskResume( TaskHandle_t pxTaskToResume );
void MPU_vTaskSuspendAll( void );
BaseType_t MPU_xTaskResumeAll( void );
@ -787,19 +786,6 @@ BaseType_t xRunningPrivileged = prvRaisePrivilege();
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
BaseType_t MPU_xTaskIsTaskSuspended( TaskHandle_t xTask )
{
BaseType_t xReturn;
BaseType_t xRunningPrivileged = prvRaisePrivilege();
xReturn = xTaskIsTaskSuspended( xTask );
portRESET_PRIVILEGE( xRunningPrivileged );
return xReturn;
}
#endif
/*-----------------------------------------------------------*/
#if ( INCLUDE_vTaskSuspend == 1 )
void MPU_vTaskResume( TaskHandle_t pxTaskToResume )
{

View File

@ -86,7 +86,7 @@ privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
/* Constants used with the cRxLock and xTxLock structure members. */
/* Constants used with the xRxLock and xTxLock structure members. */
#define queueUNLOCKED ( ( BaseType_t ) -1 )
#define queueLOCKED_UNMODIFIED ( ( BaseType_t ) 0 )
@ -1038,11 +1038,11 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
/* Similar to xQueueGenericSend, except we don't block if there is no room
in the queue. Also we don't directly wake a task that was blocked on a
queue read, instead we return a flag to say whether a context switch is
required or not (i.e. has a task with a higher priority than us been woken
by this post). */
/* Similar to xQueueGenericSend, except without blocking if there is no room
in the queue. Also don't directly wake a task that was blocked on a queue
read, instead return a flag to say whether a context switch is required or
not (i.e. has a task with a higher priority than us been woken by this
post). */
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
@ -1051,7 +1051,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
/* If the queue is locked we do not alter the event list. This will
/* The event list is not altered if the queue is locked. This will
be done when the queue is unlocked later. */
if( pxQueue->xTxLock == queueUNLOCKED )
{
@ -2349,6 +2349,8 @@ BaseType_t xReturn;
Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
BaseType_t xReturn = pdFALSE;
/* This function must be called form a critical section. */
configASSERT( pxQueueSetContainer );
configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );

View File

@ -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 UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
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 BaseType_t xYieldPending = pdFALSE;
PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
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 )
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. */
/**
* 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
* automatically upon the creation of the first task.
@ -806,9 +822,8 @@ TCB_t * pxNewTCB;
{
traceTASK_DELAY_UNTIL();
/* We must remove ourselves from the ready list before adding
ourselves to the blocked list as the same list item is used for
both lists. */
/* 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 )
{
/* The current task must be in a ready list, so there is
@ -1254,25 +1269,25 @@ TCB_t * pxNewTCB;
#if ( INCLUDE_vTaskSuspend == 1 )
BaseType_t xTaskIsTaskSuspended( const TaskHandle_t xTask )
static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
{
BaseType_t xReturn = pdFALSE;
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. */
configASSERT( xTask );
/* Is the task we are attempting to resume actually in the
suspended list? */
/* Is the task being resumed actually in the suspended list? */
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
{
/* Has the task already been resumed from within an ISR? */
if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
{
/* Is it in the suspended list because it is in the
Suspended state? It is possible to be in the suspended
list because it is blocked on a task with no timeout
specified. */
/* Is it in the suspended list because it is in the Suspended
state, or because is is blocked with no timeout? */
if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
{
xReturn = pdTRUE;
@ -1313,7 +1328,7 @@ TCB_t * pxNewTCB;
{
taskENTER_CRITICAL();
{
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
{
traceTASK_RESUME( pxTCB );
@ -1382,12 +1397,15 @@ TCB_t * pxNewTCB;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
{
if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
{
traceTASK_RESUME_FROM_ISR( pxTCB );
/* Check the ready lists can be accessed. */
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 )
{
xYieldRequired = pdTRUE;
@ -1402,9 +1420,9 @@ TCB_t * pxNewTCB;
}
else
{
/* We cannot access the delayed or ready lists, so will hold this
task pending until the scheduler is resumed, at which point a
yield will be performed if necessary. */
/* The delayed or ready lists cannot be accessed so the task
is held in the pending ready list until the scheduler is
unsuspended. */
vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
}
}
@ -2144,17 +2162,18 @@ TickType_t xTimeToWake;
configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED. */
/* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
/* 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
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 ) );
/* We must remove ourselves from the ready list before adding ourselves
to the blocked list as the same list item is used for both lists. We have
exclusive access to the ready lists as the scheduler is locked. */
/* The task must be removed from from the ready list before it is added to
the blocked list as the same list item is used for both lists. Exclusive
access to the ready lists guaranteed because the scheduler is locked. */
if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
{
/* 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 )
{
/* Add ourselves to the suspended task list instead of a delayed task
list to ensure we are not woken by a timing event. We will block
indefinitely. */
/* Add the task to the suspended task list instead of a delayed task
list to ensure the task is not woken by a timing event. It will
block indefinitely. */
vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
}
else
{
/* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter, the
scheduler will handle it. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
@ -2186,7 +2206,8 @@ TickType_t xTimeToWake;
#else /* INCLUDE_vTaskSuspend */
{
/* 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;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
@ -2200,14 +2221,20 @@ TickType_t xTimeToWake;
configASSERT( pxEventList );
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED. */
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
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 );
/* 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 ) );
/* The task must be removed from the ready list before it is added to the
@ -2235,8 +2262,9 @@ TickType_t xTimeToWake;
}
else
{
/* Calculate the time at which the task should be woken if the event does
not occur. This may overflow but this doesn't matter. */
/* Calculate the time at which the task should be woken if the event
does not occur. This may overflow but this doesn't matter, the
kernel will manage it correctly. */
xTimeToWake = xTickCount + xTicksToWait;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
@ -2244,7 +2272,8 @@ TickType_t xTimeToWake;
#else /* INCLUDE_vTaskSuspend */
{
/* 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;
prvAddCurrentTaskToDelayedList( xTimeToWake );
}
@ -2302,16 +2331,16 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
TCB_t *pxUnblockedTCB;
BaseType_t xReturn;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED. It can also be called from within an ISR. */
/* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
called from a critical section within an ISR. */
/* The event list is sorted in priority order, so we can remove the
first in the list, remove the TCB from the delayed list, and add
it to the ready list.
/* The event list is sorted in priority order, so the first in the list can
be removed as it is known to be the highest priority. Remove the TCB from
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
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
pxEventList is not empty. */
@ -2333,10 +2362,9 @@ BaseType_t xReturn;
if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* Return true if the task removed from the event list has
a higher priority than the calling task. This allows
the calling task to know if it should force a context
switch now. */
/* Return true if the task removed from the event list has a higher
priority than the calling task. This allows the calling task to know if
it should force a context switch now. */
xReturn = pdTRUE;
/* 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;
BaseType_t xReturn;
/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
SCHEDULER SUSPENDED. It can also be called from within an ISR. */
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
the event flags implementation. */
configASSERT( uxSchedulerSuspended != pdFALSE );
/* Store the new item value in the event list. */
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 );
configASSERT( pxUnblockedTCB );
( 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
lists. */
( 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 )
{
@ -2812,7 +2835,9 @@ static void prvCheckTasksWaitingTermination( void )
while( uxTasksDeleted > ( UBaseType_t ) 0U )
{
vTaskSuspendAll();
{
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
}
( void ) xTaskResumeAll();
if( xListIsEmpty == pdFALSE )
@ -2932,6 +2957,21 @@ TCB_t *pxNewTCB;
pxTaskStatusArray[ uxTask ].eCurrentState = eState;
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 )
{
pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;