New stack checking and tracing functionality

Stack overflows are the most common source of problems in FreeRTOS.org application.  I have therefore added two new features to the SVN head of tasks.c: 1) New function uxTaskGetStackHighWaterMark() as described below. /** * task.h * <PRE>unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void );</PRE> * * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for * this function to be available. * * Returns the high water mark for the stack of the calling task.  That is, * the minimum free stack space there has been (in bytes) since the task * started.  The small the returned number the closer the task has come * to overflowing its stack. */ unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( void ); 2) Stack overflow hook, as described below: /* * Call the stack overflow hook function if the stack of the task being swapped * out is currently overflowed, or looks like it might have overflowed in the * past. * * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check * the current stack state only – comparing the current top of stack value to * the stack limit.  Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 * will also cause the last few stack bytes to be checked to ensure the value * to which the bytes were set when the task was created have not been * overwritten.  Note this second test does not guarantee that an overflowed * stack will always be recognised. */ If configCHECK_FOR_STACK_OVERFLOW is set to greater than 0 then the application must provide a function with the prototype: void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ); In addition, the tasks.c and queue.c code have been laced with trace macros that permit user defined trace functionality to be implemented.  More on this later. Regards.

New stack checking and tracing functionality

I suppose that you will add these changes in next release 4.7.3, is it right? Do you add in task.c and queue.c only my proposed hooks in create functions or similar hooks in delete functions too? I think that uxTaskGetStackHighWaterMark( void ) could be better if it will provide stack high water for a generic task, something like this: uxTaskGetStackHighWaterMark( xTaskHandle taskID ) Do you think is it possible or needs very slow check? i think stack check are very important for safety reasons, but has to be very speed test! Bye, Piero

New stack checking and tracing functionality

I think this is the better place for this post (i did it in other thread) Hi Richard. Hi all. My idea about how write custom functions for stack check, using macros in create functions, is to save pxTopOfStack of each task in global var with requested stack size, when task is created. After, it could be possible check stack usage or stack free, using current pxTopOfStack  and a simple difference and compare. Function usTaskCheckFreeStackSpace could be usefull, but i think it’s slow because has to search first fill byte 0xa5. For heap usage, my idea is to have a GV memory, which contains number of bytes allocated using pvPortMalloc, based on formulas above. When a task is creted or when a queue is created, this variable will increase, when task or queue are deleted it will decrease. The value inside will give an idea of heap usage dinamically, but without care about fragmentation (see heap2 schema). I think will be a usefull information in run time or during debugging, especially when using application dynamically creates and deletes tasks (or queues, etc), i.e. using LWIP tcpip stack. I will use hooks in create e delete functions to do this, but if you think it could be usefull, this idea could be implemented in future freertos trace functions. Bye, Piero

New stack checking and tracing functionality

Hi Richard. Hi all. The current implementation of FreeRTOS allows the current task to corrupt its own TCB in case of stack overflow. In so doing a program will detect neither the stack overflow nor the according task name. The application will end up with high probability in nirvana. I think the simplest solution for this problem is to allocate TCB and its stack in one memory block. The stack should grow away from the current TCB. This would increase the diagnostics coverage for FreeRTOS bases applications. Bye, Maxim

New stack checking and tracing functionality

>I suppose that you will add these changes in next release 4.7.3, is it right? Yes the changes will be in the next release. >Do you add in task.c and queue.c only my proposed hooks in create functions >or similar hooks in delete functions too? I have added some trace events to creating/deleting tasks and queues, but I’m not sure if it covers the same information as the hooks you posted the other day or not. >I think that uxTaskGetStackHighWaterMark( void ) could be better if it will >provide stack high water for a generic task, something like this: > uxTaskGetStackHighWaterMark( xTaskHandle taskID ) Yes, good idea, I have made the change as follows (not yet checked in): /** * task.h * <PRE>unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );</PRE> * * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for * this function to be available. * * Returns the high water mark of the stack associated with xTask.  That is, * the minimum free stack space there has been (in bytes) since the task * started.  The smaller the returned number the closer the task has come * to overflowing its stack. * * @param xTask Handle of the task associated with the stack to be checked. * Set xTask to NULL to check the stack of the calling task. * * @return The smallest amount of free stack space there has been (in bytes) * since the task referenced by xTask was created. */ unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ); > Do you think is it possible or needs very slow check? i think stack check > are very important for safety reasons, but has to be very speed test! Checking the current stack level against the stack boundary is a quick test, but does not guarantee that you will catch a stack overflow (the stack could have overflowed prior to calling the checking function).  Even checking the 0xa5’s on the stack is not a guarantee. Regards.

New stack checking and tracing functionality

>The current implementation of FreeRTOS allows the current task to > corrupt its own TCB in case of stack overflow Yes this is a problem which is why both the handle and the stack name are passed to the hook function – the handle will be correct even if the name has been corrupted. BTW – SafeRTOS uses a scheme as you suggest in your post.  The stack grows away from the TCB, but you don’t know what it will bump into in the other direction. Regards.

New stack checking and tracing functionality

> Yes this is a problem which is why both the handle and the stack name are passed to the hook > function – the handle will be correct even if the name has been corrupted. Ok, but a primitive handle is not that friendly for debugging/diagnostics. > BTW – SafeRTOS uses a scheme as you suggest in your post. Do you intend to leave the TCB/stack allocation in FreeRTOS as is? > The stack grows away from the TCB, but you don’t know what it will bump into in the other direction. You’re right, but nevertheless, it increases the diagnostics coverage significantly. Since I have patched task.c as described above I cannot remember that my program landed in an exception handler as a result of stack overflow. Of course, a fast stack check is necessary after each context save.

New stack checking and tracing functionality

Hi Richard. > Checking the current stack level against the stack boundary is a quick test, > but does not guarantee that you will catch a stack overflow (the stack could > have overflowed prior to calling the checking function). Even checking the > 0xa5’s on the stack is not a guarantee. Ok, so, i can suppose that for stack check you use something like i wrote in my posts, here: http://sourceforge.net/forum/message.php?msg_id=4815045 and here: http://sourceforge.net/forum/message.php?msg_id=4815046 (it’s the same message in other thread) WITHOUT search for 0xa5, without call to usTaskCheckFreeStackSpace() function. ok, in this case, we will have a quick test, it will be possible to do this test in run-time, and do something if stack level of some task is near the boundary (i.e. 70%). It does not guarantee that we will catch a stack overflow, but it should be possible to build very robust and safety application, depending on developer code. Please, read one of my post linked above, before realease next version. Bye, Piero.

New stack checking and tracing functionality

From your other post: "My idea about how write custom functions for stack check, using macros in create functions, is to save pxTopOfStack of each task in global var with requested stack size, when task is created.  After, it could be possible check stack usage or stack free, using current pxTopOfStack and a simple difference and compare" I don’t fully understand your idea of using global variables, particularly as you don’t know how many tasks are going to be created.  One of the checks I have implemented does this: if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack )                            { ____/* Overflow caught during task switch. */ } Regards.

New stack checking and tracing functionality

Hi Richard. > I don’t fully understand your idea of using global variables, particularly as you don’t know how many tasks are going to be created. ok… sorry… i didn’t explain well…. I’m thinking about something for my application, using hooks, where i know ho many tasks will be created… For a general solution, global array is not a correct solution. I didn’t see in freertos code that pcb struct ALREADY has two fields, pxStack (start of stack) and pxTopOfStack (current top pf the stack). So, we can avoid to use GV. I think we should modify  pcb struct: #if ( configUSE_TRACE_FACILITY == 1 )     unsigned portBASE_TYPE    uxTCBNumber;                unsigned portBASE_TYPE    uxStackSize;     // stack size in bytes #endif    and define a check similar than the following: portBASE_TYPE xTaskCheckStack( xTaskHandle *pxTask , portBASE_TYPE limitPercentage) {   portBASE_TYPE xReturn;   tskTCB * pxTCB;   // search pxTask and update pxTCB!   ….   xReturn = pdFALSE;   if( (pxTCB->pxTopOfStack – pxTCB->pxStack)> ((limitPercentage * pxTCB->uxStackSize) /100) )   {    /* warning. Stack over the limit */    xReturn = pdTRUE;   }   return xReturn ; } What do you think? The second idea  i wrote in my post, is simple a global var which contains total memory allocated in heap: calls to xTaskCreate and xQueueCreate increase its value, calls to xTaskDelete and xQueueDelete decrease its value. Reading this var a developer can see in run time how many bytes application has allocated. This is a simple check, which doesn’t care about heap fragmentation (see heap2 schema) What do you think? Bye, Piero

New stack checking and tracing functionality

I would suggest storing this "((limitPercentage * pxTCB->uxStackSize) /100)" as a pre-calculated value to prevent the maths overhead. Regards.

New stack checking and tracing functionality

Hi Richard > I would suggest storing this "((limitPercentage * pxTCB->uxStackSize) /100)" as > a pre-calculated value to prevent the maths overhead. Good idea. Can i hope that something like we discuss in this thread will be in the next release, or i will have to implement the discussed idea using hooks in create e delete functions (available in the next verison, as you said)? Bye, Piero.