mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Bug fix: The 'value' of the event list item is updated when the priority of a task is changed. Previously only the priority of the TCB itself was changed.
When resuming a task a check is first made to see if the task is actually suspended. vTaskPrioritySet() and vTaskResume() no longer use the event list item. This has not been necessary since V4.0.1 when the xMissedYield handling was added.
This commit is contained in:
parent
bc141db940
commit
d481cff89b
176
Source/tasks.c
176
Source/tasks.c
|
@ -153,17 +153,28 @@ Changes from V4.0.0
|
||||||
Changes from V4.0.1
|
Changes from V4.0.1
|
||||||
|
|
||||||
+ The function vTaskList() now suspends the scheduler rather than disabling
|
+ The function vTaskList() now suspends the scheduler rather than disabling
|
||||||
interrups during the creation of the task list.
|
interrupts during the creation of the task list.
|
||||||
+ Allow a task to delete itself by passing in its own handle. Previously
|
+ Allow a task to delete itself by passing in its own handle. Previously
|
||||||
this could only be done by passing in NULL.
|
this could only be done by passing in NULL.
|
||||||
+ The tick hook function is now called only within a tick isr. Previously
|
+ The tick hook function is now called only within a tick isr. Previously
|
||||||
it was also called when the tick function was called during the scheduler
|
it was also called when the tick function was called during the scheduler
|
||||||
unlocking process.
|
unlocking process.
|
||||||
|
|
||||||
Changes from V4.0.4
|
Changes from V4.0.3
|
||||||
|
|
||||||
+ Extra checks have been placed in vTaskPrioritySet() to avoid unnecessary
|
+ Extra checks have been placed in vTaskPrioritySet() to avoid unnecessary
|
||||||
yields.
|
yields.
|
||||||
|
|
||||||
|
Changed from V4.0.4
|
||||||
|
|
||||||
|
+ Bug fix: The 'value' of the event list item is updated when the priority
|
||||||
|
of a task is changed. Previously only the priority of the TCB itself was
|
||||||
|
changed.
|
||||||
|
+ When resuming a task a check is first made to see if the task is actually
|
||||||
|
suspended.
|
||||||
|
+ vTaskPrioritySet() and vTaskResume() no longer use the event list item.
|
||||||
|
This has not been necessary since V4.0.1 when the xMissedYield handling
|
||||||
|
was added.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -290,28 +301,28 @@ static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
|
||||||
*/
|
*/
|
||||||
#if ( configUSE_TRACE_FACILITY == 1 )
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
|
||||||
#define vWriteTraceToBuffer() \
|
#define vWriteTraceToBuffer() \
|
||||||
{ \
|
{ \
|
||||||
if( xTracing ) \
|
if( xTracing ) \
|
||||||
{ \
|
{ \
|
||||||
static unsigned portBASE_TYPE uxPreviousTask = 255; \
|
static unsigned portBASE_TYPE uxPreviousTask = 255; \
|
||||||
\
|
\
|
||||||
if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \
|
if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \
|
||||||
{ \
|
{ \
|
||||||
if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \
|
if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \
|
||||||
{ \
|
{ \
|
||||||
uxPreviousTask = pxCurrentTCB->uxTCBNumber; \
|
uxPreviousTask = pxCurrentTCB->uxTCBNumber; \
|
||||||
*( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) xTickCount; \
|
*( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) xTickCount; \
|
||||||
pcTraceBuffer += sizeof( unsigned portLONG ); \
|
pcTraceBuffer += sizeof( unsigned portLONG ); \
|
||||||
*( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) uxPreviousTask; \
|
*( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) uxPreviousTask; \
|
||||||
pcTraceBuffer += sizeof( unsigned portLONG ); \
|
pcTraceBuffer += sizeof( unsigned portLONG ); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
xTracing = pdFALSE; \
|
xTracing = pdFALSE; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -337,7 +348,6 @@ static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
|
||||||
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
|
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macro that looks at the list of tasks that are currently delayed to see if
|
* Macro that looks at the list of tasks that are currently delayed to see if
|
||||||
* any require waking.
|
* any require waking.
|
||||||
|
@ -346,24 +356,24 @@ static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
|
||||||
* once one tasks has been found whose timer has not expired we need not look
|
* once one tasks has been found whose timer has not expired we need not look
|
||||||
* any further down the list.
|
* any further down the list.
|
||||||
*/
|
*/
|
||||||
#define prvCheckDelayedTasks() \
|
#define prvCheckDelayedTasks() \
|
||||||
{ \
|
{ \
|
||||||
register tskTCB *pxTCB; \
|
register tskTCB *pxTCB; \
|
||||||
\
|
\
|
||||||
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \
|
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \
|
||||||
{ \
|
{ \
|
||||||
if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \
|
if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \
|
||||||
{ \
|
{ \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
vListRemove( &( pxTCB->xGenericListItem ) ); \
|
vListRemove( &( pxTCB->xGenericListItem ) ); \
|
||||||
/* Is the task waiting on an event also? */ \
|
/* Is the task waiting on an event also? */ \
|
||||||
if( pxTCB->xEventListItem.pvContainer ) \
|
if( pxTCB->xEventListItem.pvContainer ) \
|
||||||
{ \
|
{ \
|
||||||
vListRemove( &( pxTCB->xEventListItem ) ); \
|
vListRemove( &( pxTCB->xEventListItem ) ); \
|
||||||
} \
|
} \
|
||||||
prvAddTaskToReadyQueue( pxTCB ); \
|
prvAddTaskToReadyQueue( pxTCB ); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -615,9 +625,12 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
/* Force a reschedule if we have just deleted the current task. */
|
/* Force a reschedule if we have just deleted the current task. */
|
||||||
if( ( void * ) pxTaskToDelete == NULL )
|
if( xSchedulerRunning != pdFALSE )
|
||||||
{
|
{
|
||||||
taskYIELD();
|
if( ( void * ) pxTaskToDelete == NULL )
|
||||||
|
{
|
||||||
|
taskYIELD();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,6 +844,7 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
}
|
}
|
||||||
|
|
||||||
pxTCB->uxPriority = uxNewPriority;
|
pxTCB->uxPriority = uxNewPriority;
|
||||||
|
listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxNewPriority );
|
||||||
|
|
||||||
/* If the task is in the blocked or suspended list we need do
|
/* If the task is in the blocked or suspended list we need do
|
||||||
nothing more than change it's priority variable. However, if
|
nothing more than change it's priority variable. However, if
|
||||||
|
@ -838,19 +852,11 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
in the queue appropriate to its new priority. */
|
in the queue appropriate to its new priority. */
|
||||||
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
|
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
|
||||||
{
|
{
|
||||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
/* The task is currently in its ready list - remove before adding
|
||||||
{
|
it to it's new ready list. As we are in a critical section we
|
||||||
/* The task is currently in its ready list - remove before adding
|
can do this even if the scheduler is suspended. */
|
||||||
it to it's new ready list. */
|
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
prvAddTaskToReadyQueue( pxTCB );
|
||||||
prvAddTaskToReadyQueue( pxTCB );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We cannot access the delayed or ready lists, so will hold this
|
|
||||||
task pending until the scheduler is resumed. */
|
|
||||||
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( xYieldRequired == pdTRUE )
|
if( xYieldRequired == pdTRUE )
|
||||||
|
@ -911,7 +917,6 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
void vTaskResume( xTaskHandle pxTaskToResume )
|
void vTaskResume( xTaskHandle pxTaskToResume )
|
||||||
{
|
{
|
||||||
tskTCB *pxTCB;
|
tskTCB *pxTCB;
|
||||||
portBASE_TYPE xYieldRequired;
|
|
||||||
|
|
||||||
/* Remove the task from whichever list it is currently in, and place
|
/* Remove the task from whichever list it is currently in, and place
|
||||||
it in the ready list. */
|
it in the ready list. */
|
||||||
|
@ -923,34 +928,59 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat
|
||||||
{
|
{
|
||||||
taskENTER_CRITICAL();
|
taskENTER_CRITICAL();
|
||||||
{
|
{
|
||||||
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
/* Is the task we are attempting to resume actually suspended? */
|
||||||
|
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
|
||||||
{
|
{
|
||||||
xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
|
/* As we are in a critical section we can access the ready
|
||||||
|
lists even if the scheduler is suspended. */
|
||||||
vListRemove( &( pxTCB->xGenericListItem ) );
|
vListRemove( &( pxTCB->xGenericListItem ) );
|
||||||
prvAddTaskToReadyQueue( pxTCB );
|
prvAddTaskToReadyQueue( pxTCB );
|
||||||
}
|
|
||||||
else
|
/* We may have just resumed a higher priority task. */
|
||||||
{
|
if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
|
||||||
/* We cannot access the delayed or ready lists, so will hold this
|
{
|
||||||
task pending until the scheduler is resumed. */
|
/* This yield may not cause the task just resumed to run, but
|
||||||
xYieldRequired = pdFALSE;
|
will leave the lists in the correct state for the next yield. */
|
||||||
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
|
taskYIELD();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taskEXIT_CRITICAL();
|
taskEXIT_CRITICAL();
|
||||||
|
|
||||||
/* We may have just resumed a higher priority task. */
|
|
||||||
if( xYieldRequired )
|
|
||||||
{
|
|
||||||
/* This yield may not cause the task just resumed to run, but
|
|
||||||
will leave the lists in the correct state for the next yield. */
|
|
||||||
taskYIELD();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if ( INCLUDE_vTaskResumeFromISR == 1 )
|
||||||
|
|
||||||
|
portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
|
||||||
|
{
|
||||||
|
portBASE_TYPE xYieldRequired;
|
||||||
|
|
||||||
|
/* Is the task we are attempting to resume actually suspended? */
|
||||||
|
if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTaskToResume->xGenericListItem ) ) != pdFALSE )
|
||||||
|
{
|
||||||
|
if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
|
||||||
|
{
|
||||||
|
xYieldRequired = ( pxTaskToResume->uxPriority >= pxCurrentTCB->uxPriority );
|
||||||
|
vListRemove( &( pxTaskToResume->xGenericListItem ) );
|
||||||
|
prvAddTaskToReadyQueue( pxTaskToResume );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We cannot access the delayed or ready lists, so will hold this
|
||||||
|
task pending until the scheduler is resumed. */
|
||||||
|
xYieldRequired = pdFALSE;
|
||||||
|
vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTaskToResume->xEventListItem ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return xYieldRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue