|
|
|
@ -89,13 +89,17 @@ typedef struct tskTaskControlBlock
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ( configUSE_MUTEXES == 1 )
|
|
|
|
|
unsigned portBASE_TYPE uxBasePriority;
|
|
|
|
|
unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
|
|
|
|
pdTASK_HOOK_CODE pxTaskTag;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
|
unsigned portLONG ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
} tskTCB;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -144,6 +148,14 @@ static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
|
|
|
|
|
static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
|
|
|
|
|
static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
|
|
|
|
|
|
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
|
|
|
|
|
|
static portCHAR pcStatsString[ 50 ];
|
|
|
|
|
static unsigned portLONG ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
|
|
|
|
|
static void prvGenerateRunTimeStatsForTasksInList( const signed portCHAR *pcWriteBuffer, xList *pxList, unsigned portLONG ulTotalRunTime );
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Debugging and trace facilities private variables and macros. ------------*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -172,6 +184,7 @@ static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
|
|
|
|
|
static signed portBASE_TYPE xTracing = pdFALSE;
|
|
|
|
|
static unsigned portBASE_TYPE uxPreviousTask = 255;
|
|
|
|
|
static portCHAR pcStatusString[ 50 ];
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
@ -303,7 +316,9 @@ static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
|
|
|
|
|
* allocated by calls to pvPortMalloc from within the tasks application code).
|
|
|
|
|
*/
|
|
|
|
|
#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
|
|
|
|
|
|
|
|
|
|
static void prvDeleteTCB( tskTCB *pxTCB );
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -826,7 +841,7 @@ tskTCB * pxNewTCB;
|
|
|
|
|
/* If null is passed in here then we are suspending ourselves. */
|
|
|
|
|
pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );
|
|
|
|
|
|
|
|
|
|
traceTASK_SUSPEND( pxTaskToSuspend );
|
|
|
|
|
traceTASK_SUSPEND( pxTCB );
|
|
|
|
|
|
|
|
|
|
/* Remove task from the ready/delayed list and place in the suspended list. */
|
|
|
|
|
vListRemove( &( pxTCB->xGenericListItem ) );
|
|
|
|
@ -987,6 +1002,11 @@ portBASE_TYPE xReturn;
|
|
|
|
|
xSchedulerRunning = pdTRUE;
|
|
|
|
|
xTickCount = ( portTickType ) 0;
|
|
|
|
|
|
|
|
|
|
/* If configGENERATE_RUN_TIME_STATS is defined then the following
|
|
|
|
|
macro must be defined to configure the timer/counter used to generate
|
|
|
|
|
the run time counter time base. */
|
|
|
|
|
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
|
|
|
|
|
|
|
|
|
|
/* Setting up the timer tick is hardware specific and thus in the
|
|
|
|
|
portable interface. */
|
|
|
|
|
if( xPortStartScheduler() )
|
|
|
|
@ -1126,7 +1146,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_vTaskDelete == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
|
|
|
|
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
|
|
|
|
|
|
|
|
|
void vTaskList( signed portCHAR *pcWriteBuffer )
|
|
|
|
|
{
|
|
|
|
@ -1165,16 +1185,89 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
|
|
|
|
|
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if( INCLUDE_vTaskDelete == 1 )
|
|
|
|
|
{
|
|
|
|
|
if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
|
|
|
|
|
{
|
|
|
|
|
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
|
|
{
|
|
|
|
|
if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
|
|
|
|
{
|
|
|
|
|
prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
xTaskResumeAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
/*----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
|
|
|
|
|
|
void vTaskGetRunTimeStats( signed portCHAR *pcWriteBuffer )
|
|
|
|
|
{
|
|
|
|
|
unsigned portBASE_TYPE uxQueue;
|
|
|
|
|
unsigned portLONG ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
|
|
|
|
|
|
|
|
|
|
/* This is a VERY costly function that should be used for debug only.
|
|
|
|
|
It leaves interrupts disabled for a LONG time. */
|
|
|
|
|
|
|
|
|
|
vTaskSuspendAll();
|
|
|
|
|
{
|
|
|
|
|
/* Run through all the lists that could potentially contain a TCB,
|
|
|
|
|
generating a table of run timer percentages in the provided
|
|
|
|
|
buffer. */
|
|
|
|
|
|
|
|
|
|
pcWriteBuffer[ 0 ] = ( signed portCHAR ) 0x00;
|
|
|
|
|
strcat( ( portCHAR * ) pcWriteBuffer, ( const portCHAR * ) "\r\n" );
|
|
|
|
|
|
|
|
|
|
uxQueue = uxTopUsedPriority + 1;
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
uxQueue--;
|
|
|
|
|
|
|
|
|
|
if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
|
|
|
|
|
{
|
|
|
|
|
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime );
|
|
|
|
|
}
|
|
|
|
|
}while( uxQueue > ( unsigned portSHORT ) tskIDLE_PRIORITY );
|
|
|
|
|
|
|
|
|
|
if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
|
|
|
|
|
{
|
|
|
|
|
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
|
|
|
|
|
{
|
|
|
|
|
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if ( INCLUDE_vTaskDelete == 1 )
|
|
|
|
|
{
|
|
|
|
|
if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
|
|
|
|
|
{
|
|
|
|
|
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
|
|
{
|
|
|
|
|
if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
|
|
|
|
|
{
|
|
|
|
|
prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
xTaskResumeAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1394,6 +1487,21 @@ void vTaskSwitchContext( void )
|
|
|
|
|
{
|
|
|
|
|
traceTASK_SWITCHED_OUT();
|
|
|
|
|
|
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
|
{
|
|
|
|
|
unsigned portLONG ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
|
|
|
|
|
|
|
|
|
|
/* Add the amount of time the task has been running to the accumulated
|
|
|
|
|
time so far. The time the task started running was stored in
|
|
|
|
|
ulTaskSwitchedInTime. Note that there is no overflow protection here
|
|
|
|
|
so count values are only valid until the timer overflows. Generally
|
|
|
|
|
this will be about 1 hour assuming a 1uS timer increment. */
|
|
|
|
|
pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime );
|
|
|
|
|
ulTaskSwitchedInTime = ulTempCounter;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
|
|
|
|
|
{
|
|
|
|
|
/* The scheduler is currently suspended - do not allow a context
|
|
|
|
@ -1709,6 +1817,12 @@ static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed portCHAR * co
|
|
|
|
|
pxTCB->pxTaskTag = NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
|
{
|
|
|
|
|
pxTCB->ulRunTimeCounter = 0UL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
@ -1833,6 +1947,38 @@ tskTCB *pxNewTCB;
|
|
|
|
|
#endif
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#if ( configGENERATE_RUN_TIME_STATS == 1 )
|
|
|
|
|
|
|
|
|
|
static void prvGenerateRunTimeStatsForTasksInList( const signed portCHAR *pcWriteBuffer, xList *pxList, unsigned portLONG ulTotalRunTime )
|
|
|
|
|
{
|
|
|
|
|
volatile tskTCB *pxNextTCB, *pxFirstTCB;
|
|
|
|
|
unsigned portLONG ulStatsAsPercentage;
|
|
|
|
|
|
|
|
|
|
/* Write the run time stats of all the TCB's in pxList into the buffer. */
|
|
|
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
|
|
|
|
|
|
|
|
|
|
ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime;
|
|
|
|
|
|
|
|
|
|
if( ulStatsAsPercentage > 0UL )
|
|
|
|
|
{
|
|
|
|
|
sprintf( pcStatsString, ( portCHAR * ) "%s\t\t\t%lu\t\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sprintf( pcStatsString, ( portCHAR * ) "%s\t\t\t%lu\t\t\t< 1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcat( ( portCHAR * ) pcWriteBuffer, ( portCHAR * ) pcStatsString );
|
|
|
|
|
|
|
|
|
|
} while( pxNextTCB != pxFirstTCB );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
|
|
|
|
|
|
|
|
|
|
unsigned portSHORT usTaskCheckFreeStackSpace( const unsigned portCHAR * pucStackByte )
|
|
|
|
|