Changes from V4.0.1\r
\r
+ The function vTaskList() now suspends the scheduler rather than disabling\r
- interrups during the creation of the task list. \r
+ interrupts during the creation of the task list. \r
+ Allow a task to delete itself by passing in its own handle. Previously \r
this could only be done by passing in NULL.\r
+ The tick hook function is now called only within a tick isr. Previously\r
it was also called when the tick function was called during the scheduler\r
unlocking process.\r
\r
-Changes from V4.0.4\r
+Changes from V4.0.3\r
\r
+ Extra checks have been placed in vTaskPrioritySet() to avoid unnecessary\r
yields.\r
+\r
+Changed from V4.0.4\r
+\r
+ + Bug fix: The 'value' of the event list item is updated when the priority\r
+ of a task is changed. Previously only the priority of the TCB itself was\r
+ changed.\r
+ + When resuming a task a check is first made to see if the task is actually\r
+ suspended.\r
+ + vTaskPrioritySet() and vTaskResume() no longer use the event list item.\r
+ This has not been necessary since V4.0.1 when the xMissedYield handling\r
+ was added.\r
*/\r
\r
#include <stdio.h>\r
*/\r
#if ( configUSE_TRACE_FACILITY == 1 )\r
\r
- #define vWriteTraceToBuffer() \\r
- { \\r
- if( xTracing ) \\r
- { \\r
- static unsigned portBASE_TYPE uxPreviousTask = 255; \\r
- \\r
- if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \\r
- { \\r
- if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \\r
- { \\r
- uxPreviousTask = pxCurrentTCB->uxTCBNumber; \\r
+ #define vWriteTraceToBuffer() \\r
+ { \\r
+ if( xTracing ) \\r
+ { \\r
+ static unsigned portBASE_TYPE uxPreviousTask = 255; \\r
+ \\r
+ if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \\r
+ { \\r
+ if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \\r
+ { \\r
+ uxPreviousTask = pxCurrentTCB->uxTCBNumber; \\r
*( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) xTickCount; \\r
- pcTraceBuffer += sizeof( unsigned portLONG ); \\r
+ pcTraceBuffer += sizeof( unsigned portLONG ); \\r
*( unsigned portLONG * ) pcTraceBuffer = ( unsigned portLONG ) uxPreviousTask; \\r
- pcTraceBuffer += sizeof( unsigned portLONG ); \\r
- } \\r
- else \\r
- { \\r
- xTracing = pdFALSE; \\r
- } \\r
- } \\r
- } \\r
+ pcTraceBuffer += sizeof( unsigned portLONG ); \\r
+ } \\r
+ else \\r
+ { \\r
+ xTracing = pdFALSE; \\r
+ } \\r
+ } \\r
+ } \\r
}\r
\r
#else\r
uxTopReadyPriority = pxTCB->uxPriority; \\r
} \\r
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \\r
-} \r
-\r
+} \r
\r
/*\r
* Macro that looks at the list of tasks that are currently delayed to see if\r
* once one tasks has been found whose timer has not expired we need not look\r
* any further down the list.\r
*/\r
-#define prvCheckDelayedTasks() \\r
-{ \\r
-register tskTCB *pxTCB; \\r
- \\r
- while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \\r
- { \\r
- if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \\r
- { \\r
- break; \\r
- } \\r
- vListRemove( &( pxTCB->xGenericListItem ) ); \\r
- /* Is the task waiting on an event also? */ \\r
- if( pxTCB->xEventListItem.pvContainer ) \\r
- { \\r
- vListRemove( &( pxTCB->xEventListItem ) ); \\r
- } \\r
+#define prvCheckDelayedTasks() \\r
+{ \\r
+register tskTCB *pxTCB; \\r
+ \\r
+ while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \\r
+ { \\r
+ if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \\r
+ { \\r
+ break; \\r
+ } \\r
+ vListRemove( &( pxTCB->xGenericListItem ) ); \\r
+ /* Is the task waiting on an event also? */ \\r
+ if( pxTCB->xEventListItem.pvContainer ) \\r
+ { \\r
+ vListRemove( &( pxTCB->xEventListItem ) ); \\r
+ } \\r
prvAddTaskToReadyQueue( pxTCB ); \\r
- } \\r
+ } \\r
} \r
\r
/*\r
taskEXIT_CRITICAL();\r
\r
/* Force a reschedule if we have just deleted the current task. */\r
- if( ( void * ) pxTaskToDelete == NULL )\r
+ if( xSchedulerRunning != pdFALSE ) \r
{\r
- taskYIELD();\r
+ if( ( void * ) pxTaskToDelete == NULL )\r
+ {\r
+ taskYIELD();\r
+ }\r
}\r
}\r
\r
}\r
\r
pxTCB->uxPriority = uxNewPriority;\r
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxNewPriority );\r
\r
/* If the task is in the blocked or suspended list we need do\r
nothing more than change it's priority variable. However, if\r
in the queue appropriate to its new priority. */\r
if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )\r
{\r
- if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
- {\r
- /* The task is currently in its ready list - remove before adding\r
- it to it's new ready list. */\r
- vListRemove( &( pxTCB->xGenericListItem ) );\r
- prvAddTaskToReadyQueue( pxTCB );\r
- }\r
- else\r
- {\r
- /* We cannot access the delayed or ready lists, so will hold this\r
- task pending until the scheduler is resumed. */\r
- vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
- }\r
+ /* The task is currently in its ready list - remove before adding\r
+ it to it's new ready list. As we are in a critical section we\r
+ can do this even if the scheduler is suspended. */\r
+ vListRemove( &( pxTCB->xGenericListItem ) );\r
+ prvAddTaskToReadyQueue( pxTCB );\r
} \r
\r
if( xYieldRequired == pdTRUE )\r
void vTaskResume( xTaskHandle pxTaskToResume )\r
{\r
tskTCB *pxTCB;\r
- portBASE_TYPE xYieldRequired;\r
\r
/* Remove the task from whichever list it is currently in, and place\r
it in the ready list. */\r
{\r
taskENTER_CRITICAL();\r
{\r
- if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
+ /* Is the task we are attempting to resume actually suspended? */\r
+ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
{\r
- xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );\r
+ /* As we are in a critical section we can access the ready \r
+ lists even if the scheduler is suspended. */\r
vListRemove( &( pxTCB->xGenericListItem ) );\r
prvAddTaskToReadyQueue( pxTCB );\r
- }\r
- else\r
- {\r
- /* We cannot access the delayed or ready lists, so will hold this\r
- task pending until the scheduler is resumed. */\r
- xYieldRequired = pdFALSE;\r
- vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
+\r
+ /* We may have just resumed a higher priority task. */\r
+ if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
+ {\r
+ /* This yield may not cause the task just resumed to run, but\r
+ will leave the lists in the correct state for the next yield. */\r
+ taskYIELD();\r
+ }\r
}\r
}\r
taskEXIT_CRITICAL();\r
+ }\r
+ }\r
+\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
\r
- /* We may have just resumed a higher priority task. */\r
- if( xYieldRequired )\r
+#if ( INCLUDE_vTaskResumeFromISR == 1 )\r
+\r
+ portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )\r
+ {\r
+ portBASE_TYPE xYieldRequired;\r
+\r
+ /* Is the task we are attempting to resume actually suspended? */\r
+ if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTaskToResume->xGenericListItem ) ) != pdFALSE )\r
+ {\r
+ if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
{\r
- /* This yield may not cause the task just resumed to run, but\r
- will leave the lists in the correct state for the next yield. */\r
- taskYIELD();\r
+ xYieldRequired = ( pxTaskToResume->uxPriority >= pxCurrentTCB->uxPriority );\r
+ vListRemove( &( pxTaskToResume->xGenericListItem ) );\r
+ prvAddTaskToReadyQueue( pxTaskToResume );\r
+ }\r
+ else\r
+ {\r
+ /* We cannot access the delayed or ready lists, so will hold this\r
+ task pending until the scheduler is resumed. */\r
+ xYieldRequired = pdFALSE;\r
+ vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTaskToResume->xEventListItem ) );\r
}\r
}\r
+\r
+ return xYieldRequired;\r
}\r
\r
#endif\r
\r
\r
\r
-\r
/*-----------------------------------------------------------\r
* PUBLIC SCHEDULER CONTROL documented in task.h\r
*----------------------------------------------------------*/\r