From ef18df607158ac0835183fb98050863d880df8b4 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Mon, 3 Jul 2006 19:34:28 +0000 Subject: [PATCH] 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. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@18 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/tasks.c | 174 +++++++++++++++++++++++++++++-------------------- 1 file changed, 102 insertions(+), 72 deletions(-) diff --git a/Source/tasks.c b/Source/tasks.c index d6b468e16..416342363 100644 --- a/Source/tasks.c +++ b/Source/tasks.c @@ -153,17 +153,28 @@ Changes from V4.0.0 Changes from V4.0.1 + 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 this could only be done by passing in NULL. + 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 unlocking process. -Changes from V4.0.4 +Changes from V4.0.3 + Extra checks have been placed in vTaskPrioritySet() to avoid unnecessary 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 @@ -290,28 +301,28 @@ static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; */ #if ( configUSE_TRACE_FACILITY == 1 ) - #define vWriteTraceToBuffer() \ - { \ - if( xTracing ) \ - { \ - static unsigned portBASE_TYPE uxPreviousTask = 255; \ - \ - if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ - { \ - if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ - { \ - uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ + #define vWriteTraceToBuffer() \ + { \ + if( xTracing ) \ + { \ + static unsigned portBASE_TYPE uxPreviousTask = 255; \ + \ + if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ + { \ + if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ + { \ + uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) xTickCount; \ - pcTraceBuffer += sizeof( unsigned portLONG ); \ + pcTraceBuffer += sizeof( unsigned portLONG ); \ *( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) uxPreviousTask; \ - pcTraceBuffer += sizeof( unsigned portLONG ); \ - } \ - else \ - { \ - xTracing = pdFALSE; \ - } \ - } \ - } \ + pcTraceBuffer += sizeof( unsigned portLONG ); \ + } \ + else \ + { \ + xTracing = pdFALSE; \ + } \ + } \ + } \ } #else @@ -335,8 +346,7 @@ static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; uxTopReadyPriority = pxTCB->uxPriority; \ } \ vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \ -} - +} /* * Macro that looks at the list of tasks that are currently delayed to see if @@ -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 * any further down the list. */ -#define prvCheckDelayedTasks() \ -{ \ -register tskTCB *pxTCB; \ - \ - while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \ - { \ - if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \ - { \ - break; \ - } \ - vListRemove( &( pxTCB->xGenericListItem ) ); \ - /* Is the task waiting on an event also? */ \ - if( pxTCB->xEventListItem.pvContainer ) \ - { \ - vListRemove( &( pxTCB->xEventListItem ) ); \ - } \ +#define prvCheckDelayedTasks() \ +{ \ +register tskTCB *pxTCB; \ + \ + while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \ + { \ + if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \ + { \ + break; \ + } \ + vListRemove( &( pxTCB->xGenericListItem ) ); \ + /* Is the task waiting on an event also? */ \ + if( pxTCB->xEventListItem.pvContainer ) \ + { \ + vListRemove( &( pxTCB->xEventListItem ) ); \ + } \ prvAddTaskToReadyQueue( pxTCB ); \ - } \ + } \ } /* @@ -615,9 +625,12 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat taskEXIT_CRITICAL(); /* 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; + listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxNewPriority ); /* If the task is in the blocked or suspended list we need do 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. */ 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. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - 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 ) ); - } + /* 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 + can do this even if the scheduler is suspended. */ + vListRemove( &( pxTCB->xGenericListItem ) ); + prvAddTaskToReadyQueue( pxTCB ); } if( xYieldRequired == pdTRUE ) @@ -911,7 +917,6 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat void vTaskResume( xTaskHandle pxTaskToResume ) { tskTCB *pxTCB; - portBASE_TYPE xYieldRequired; /* Remove the task from whichever list it is currently in, and place it in the ready list. */ @@ -923,30 +928,56 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat { 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 ) ); prvAddTaskToReadyQueue( pxTCB ); - } - 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 ), &( pxTCB->xEventListItem ) ); + + /* We may have just resumed a higher priority task. */ + if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) + { + /* 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(); + } } } taskEXIT_CRITICAL(); + } + } + +#endif + +/*-----------------------------------------------------------*/ - /* We may have just resumed a higher priority task. */ - if( xYieldRequired ) +#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 ) { - /* 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(); + 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 @@ -954,7 +985,6 @@ static unsigned portBASE_TYPE uxTaskNumber = 0; /*lint !e956 Static is deliberat - /*----------------------------------------------------------- * PUBLIC SCHEDULER CONTROL documented in task.h *----------------------------------------------------------*/ -- 2.39.5