Determining optimal stack usage.

znatok wrote on Monday, December 08, 2014:

HI,
I have a project with 10 to 20 tasks running depending on configuration and
active connections (TCP server, …).
I want to optimize stack usage by every single task and for that I’m about
to use
uxTaskGetStackHighWaterMark()
http://www.freertos.org/uxTaskGetStackHighWaterMark.html

But I’d like to check stack usage of all tasks and not only some specific.
So I need a functionality to walk over all tasks. Unfortunately I do not
see a way to do it without turning on costly configUSE_TRACE_FACILITY . From
the other hand scheduler must have a list or lists of ALL tasks somewhere
and this should not be related to TRACE_FACILITY. My question is if I can
get access to task handlers list(s) without TRACE_FACILITY ?

davedoors wrote on Monday, December 08, 2014:

The Eclipse, IAR, and various other, IDE plugins will show you the RAM usage. Otherwise temporarily hack the code to loose the configUSE_TRACE_FACILITY guards then use uxTaskGetSystemState().

znatok wrote on Monday, December 08, 2014:

I do not use IDE. I need to get stack real time usage information.
Still is where a way to get access to the task handlers list in some way?

On Mon, Dec 8, 2014 at 7:49 PM, Dave davedoors@users.sf.net wrote:

The Eclipse, IAR, and various other, IDE plugins will show you the RAM
usage. Otherwise temporarily hack the code to loose the
configUSE_TRACE_FACILITY guards then use uxTaskGetSystemState().

Determining optimal stack usage.
https://sourceforge.net/p/freertos/discussion/382005/thread/f3164f7d/?limit=25#cb43

Sent from sourceforge.net because you indicated interest in
SourceForge.net: Log In to SourceForge.net

To unsubscribe from further messages, please visit
SourceForge.net: Log In to SourceForge.net

markwrichardson wrote on Tuesday, December 09, 2014:

I did the following . . .

The current running job info is application specific, but you should get
the idea

//======================================================================
//
//	notes for below
//======================================================================
/*
	-- TaskStatus_t type
    TaskHandle_t 			xHandle 				- The handle of the task
    const signed char *		pcTaskName				- A pointer to the task's name
    unsigned BaseType_t 	xTaskNumber 			- A number unique to the task
    eTaskState 				eCurrentState			- Task state
    unsigned BaseType_t 	uxCurrentPriority 		- task Priority
    unsigned BaseType_t	 	uxBasePriority  		- Normal Priority
    unsigned long 			ulRunTimeCounter		- Total Run time
    unsigned short 			usStackHighWaterMark	- smallest stack remaining so far
	
    eTaskState
	'G'	eRunning = 0,	 A task is querying the state of itself, so must be running. 
	'R'	eReady,			 The task being queried is in a read or pending ready list. 
	'B'	eBlocked,		 The task being queried is in the Blocked state.
	'S'	eSuspended,		 The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. 
	'D'	eDeleted		 The task being queried has been deleted, but its TCB has not yet been freed. 
*/

// put here instead of altering the distro
void *  xTimerGetTimerDaemonTaskHandle( void );

//{ "TASKLIST",	"Show all tasks and stats",		0,0, "",	 				{ 0 },	 					0, 'N', ' ', 's', '=', &cmd_TASKLIST },
//======================================================================
//
//	report task statistics to the console
//======================================================================
int cmd_TASKLIST( CMDARG *args ) 
{
	TaskStatus_t		TaskInfo[1 + TC_BASICTASKS + TC_MAXJOBTASKS + 1];
	unsigned portCHAR	TaskCnt;
	unsigned portLONG	TotalRunTime;
	unsigned portCHAR	TaskIdx;
	portCHAR			st;
	size_t				FreeHeap;
	TASKCTLITEM			*pTCI;
	char				CmdString[41];
	char				Jobstate;
	CMDJOBNO			JobNumber;
	uint16_t			StackSize;
	char				LockListBuffer[100];
	
	vTaskSuspendAll();
	
	TaskCnt = uxTaskGetSystemState( TaskInfo, (1 + TC_BASICTASKS + TC_MAXJOBTASKS + 1), &TotalRunTime);

	CIOCommandOutLine("Name           Tn S  P  p RunTime StkRmn/StkSiz St JobNum CmdString");
		
	
	for(TaskIdx = 0; TaskIdx < TaskCnt; TaskIdx ++)
	{
		switch (TaskInfo[TaskIdx].eCurrentState)
		{
			case eRunning:
				st = 'G';
				break;
			case eReady:
				st = 'r';
				break;
			case eBlocked:
				st = 'b';
				break;
			case eSuspended:
				st = 's';
				break;
			case eDeleted:
				st = 'd';
				break;
			default:
				st = '?';
				break;
		};
		
		pTCI = (TASKCTLITEM *) xTaskGetApplicationTaskTag( TaskInfo[TaskIdx].xHandle );
			
		if (pTCI)
		{
			if (pTCI->Job )				// JobInfo gets set to zero after Jobstate;
			{
				strncpy(CmdString, pTCI->Job->Args.cmdinput, 40);
			}

			JobNumber = pTCI->Job->JobNo;
			Jobstate = pTCI->JobState;		// get Jobstate after and test in case job ends
			StackSize = pTCI->StackSize;
			
			if (Jobstate != TC_NOJOB)
			{
				CmdString[40] = 0;
				LockListBuffer[0] = 0;
				RSLMakeListAllDomainLocksForTaskId( pTCI, LockListBuffer );
			}
			else
			{
				// if no job, don't trust job info
				CmdString[0] = 0;		
				JobNumber = 0;
				Jobstate = ' ';
				LockListBuffer[0] = 0;
			}
		}
		else
		{
			if (TaskInfo[TaskIdx].xHandle == xTaskGetIdleTaskHandle())
			{
				Jobstate = ' ';
				CmdString[0] = 0;
				JobNumber = 0;
				StackSize = configMINIMAL_STACK_SIZE;
			}
			else if (TaskInfo[TaskIdx].xHandle == xTimerGetTimerDaemonTaskHandle())
			{
				Jobstate = ' ';
				CmdString[0] = 0;
				JobNumber = 0;
				StackSize = configTIMER_TASK_STACK_DEPTH;
			}
			else
			{
				Jobstate = ' ';
				CmdString[0] = 0;
				JobNumber = 0;
				StackSize = 0;
			}
		}
			
		CIOCommandOutLine("%-*.*s %2d %c %2d %2d %7ld %6d/%6d  %c %6d %-40.40s", 
			14,
			configMAX_TASK_NAME_LEN-1,
			TaskInfo[TaskIdx].pcTaskName,
			TaskInfo[TaskIdx].xTaskNumber,
			st,
			TaskInfo[TaskIdx].uxCurrentPriority,
			TaskInfo[TaskIdx].uxBasePriority,
			TaskInfo[TaskIdx].ulRunTimeCounter,
			TaskInfo[TaskIdx].usStackHighWaterMark,
			StackSize,
			Jobstate,
			JobNumber,
			CmdString	);

		if ( LockListBuffer[0] != 0 )
			CIOCommandOutLine( " - Locks held: %s", LockListBuffer ); 
	}

	FreeHeap = xPortGetFreeHeapSize();
	CIOCommandOutLine( "Heap Remaining = %u of %u", FreeHeap, configTOTAL_HEAP_SIZE);
	CIOCommandOutLine( "Active Job Count = %u", UCL_GetActiveJobCount() );
	
	xTaskResumeAll();
	
	return 0;
}

znatok wrote on Tuesday, December 09, 2014:

Hi Mark.
I do not want to use
configUSE_TRACE_FACILITY and uxTaskGetSystemState().

I need access to tasks list but without tracing on as it is costly.

Sent from my iPad

On Dec 9, 2014, at 5:56 AM, "Mark " markwrichardson@users.sf.net wrote:

I did the following . . .
The current running job info is application specific, but you should get
the idea

//======================================================================
//
// notes for below
//======================================================================
/*
– TaskStatus_t type
TaskHandle_t xHandle - The handle of the task
const signed char * pcTaskName - A pointer to the task’s name
unsigned BaseType_t xTaskNumber - A number unique to the task
eTaskState eCurrentState - Task state
unsigned BaseType_t uxCurrentPriority - task Priority
unsigned BaseType_t uxBasePriority - Normal Priority
unsigned long ulRunTimeCounter - Total Run time
unsigned short usStackHighWaterMark - smallest stack remaining so far

eTaskState
'G' eRunning = 0,    A task is querying the state of itself, so must be running. 
'R' eReady,          The task being queried is in a read or pending ready list. 
'B' eBlocked,        The task being queried is in the Blocked state.
'S' eSuspended,      The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. 
'D' eDeleted         The task being queried has been deleted, but its TCB has not yet been freed. 

*/

// put here instead of altering the distro
void * xTimerGetTimerDaemonTaskHandle( void );

//{ “TASKLIST”, “Show all tasks and stats”, 0,0, “”, { 0 }, 0, ‘N’, ’ ', ‘s’, ‘=’, &cmd_TASKLIST },
//======================================================================
//
// report task statistics to the console
//======================================================================
int cmd_TASKLIST( CMDARG *args )
{
TaskStatus_t TaskInfo[1 + TC_BASICTASKS + TC_MAXJOBTASKS + 1];
unsigned portCHAR TaskCnt;
unsigned portLONG TotalRunTime;
unsigned portCHAR TaskIdx;
portCHAR st;
size_t FreeHeap;
TASKCTLITEM *pTCI;
char CmdString[41];
char Jobstate;
CMDJOBNO JobNumber;
uint16_t StackSize;
char LockListBuffer[100];

vTaskSuspendAll();

TaskCnt = uxTaskGetSystemState( TaskInfo, (1 + TC_BASICTASKS + TC_MAXJOBTASKS + 1), &TotalRunTime);

CIOCommandOutLine("Name           Tn S  P  p RunTime StkRmn/StkSiz St JobNum CmdString");

for(TaskIdx = 0; TaskIdx < TaskCnt; TaskIdx ++)
{
    switch (TaskInfo[TaskIdx].eCurrentState)
    {
        case eRunning:
            st = 'G';
            break;
        case eReady:
            st = 'r';
            break;
        case eBlocked:
            st = 'b';
            break;
        case eSuspended:
            st = 's';
            break;
        case eDeleted:
            st = 'd';
            break;
        default:
            st = '?';
            break;
    };

    pTCI = (TASKCTLITEM *) xTaskGetApplicationTaskTag( TaskInfo[TaskIdx].xHandle );

    if (pTCI)
    {
        if (pTCI->Job )             // JobInfo gets set to zero after Jobstate;
        {
            strncpy(CmdString, pTCI->Job->Args.cmdinput, 40);
        }

        JobNumber = pTCI->Job->JobNo;
        Jobstate = pTCI->JobState;      // get Jobstate after and test in case job ends
        StackSize = pTCI->StackSize;

        if (Jobstate != TC_NOJOB)
        {
            CmdString[40] = 0;
            LockListBuffer[0] = 0;
            RSLMakeListAllDomainLocksForTaskId( pTCI, LockListBuffer );
        }
        else
        {
            // if no job, don't trust job info
            CmdString[0] = 0;       
            JobNumber = 0;
            Jobstate = ' ';
            LockListBuffer[0] = 0;
        }
    }
    else
    {
        if (TaskInfo[TaskIdx].xHandle == xTaskGetIdleTaskHandle())
        {
            Jobstate = ' ';
            CmdString[0] = 0;
            JobNumber = 0;
            StackSize = configMINIMAL_STACK_SIZE;
        }
        else if (TaskInfo[TaskIdx].xHandle == xTimerGetTimerDaemonTaskHandle())
        {
            Jobstate = ' ';
            CmdString[0] = 0;
            JobNumber = 0;
            StackSize = configTIMER_TASK_STACK_DEPTH;
        }
        else
        {
            Jobstate = ' ';
            CmdString[0] = 0;
            JobNumber = 0;
            StackSize = 0;
        }
    }

    CIOCommandOutLine("%-*.*s %2d %c %2d %2d %7ld %6d/%6d  %c %6d %-40.40s", 
        14,
        configMAX_TASK_NAME_LEN-1,
        TaskInfo[TaskIdx].pcTaskName,
        TaskInfo[TaskIdx].xTaskNumber,
        st,
        TaskInfo[TaskIdx].uxCurrentPriority,
        TaskInfo[TaskIdx].uxBasePriority,
        TaskInfo[TaskIdx].ulRunTimeCounter,
        TaskInfo[TaskIdx].usStackHighWaterMark,
        StackSize,
        Jobstate,
        JobNumber,
        CmdString   );

    if ( LockListBuffer[0] != 0 )
        CIOCommandOutLine( " - Locks held: %s", LockListBuffer ); 
}

FreeHeap = xPortGetFreeHeapSize();
CIOCommandOutLine( "Heap Remaining = %u of %u", FreeHeap, configTOTAL_HEAP_SIZE);
CIOCommandOutLine( "Active Job Count = %u", UCL_GetActiveJobCount() );

xTaskResumeAll();

return 0;

}
Determining optimal stack usage.

Sent from sourceforge.net because you indicated interest in SourceForge.net: Log In to SourceForge.net

To unsubscribe from further messages, please visit SourceForge.net: Log In to SourceForge.net

rtel wrote on Tuesday, December 09, 2014:

uxTaskGetSystemState() is the function provided to do this. If you
don’t want to use that function then I’m afraid the only way is to
provide your own, which will mean adding your own code to the FreeRTOS
tasks.c file. You can copy the way uxTaskGetSystemState() does it, but
if you are going to copy the way it does it, it would seem to make sense
to instead edit tasks.c to just remove the need for
configUSE_TRACE_FACILITY to be defined.

FreeRTOS has always employed strict data hiding as a principal of good
engineering practice, so without adding your own code into tasks.c, or
using the API function already provided to do this, there is no other
way as that is the only file in which the information you need is
accessible.

Regards.