A comment/question after investigating some stack usage protection in freeRTOS 8.2.3. This post is about tasks.c, prvAllocateTCBAndStack(). Believe the feature of allocating stack/TCB, so that stack would grow away from its TCB block was added in 8.2.0. But is really allocating TCB and stack in separate alloc steps ensuring the intended protection in all use cases? What if one has a heap implementation that supports free? In that case, one can foresee the possibility that the allocation of the TCB and stack do not get the intended order in memory due to heap fragmentation. Wouldn’t it be better (and possibly also simpler) to allocate the TCB and stack in one go; including required additional bytes for stack alignment if TCB is not a multiple of StackType_t? Admittedly, I haven’t investigated all the various freeRTOS heap implementations, and this is not a problem for me; since I am not supporting free in the applications I am working with.
You are right in that, if a task is created after many allocations and frees, the memory used to create the tasks could come from anywhere. In small dedicated systems, most if not all tasks are created before any memory has been freed, and in that use case the ordering will ensure the stack doesn’t grow into the TCB (which is a debate that has been going on for a long time – in my opinion it is best for an overflowed stack to corrupt the offending task, rather than a different task, but I lost that argument on the basis that a task corrupting its own TCB makes it harder to identify the offending task). FreeRTOS V9 (not yet released!) also allows the user to provide the memory used to hold the task stack and TCB (as well as the memory to hold any other objects such as queues, semaphores, event groups, timers, etc.).
Richard, I am definitely on your side about having the offending task corrupt its own stack. I think it is more difficult to debug when another task offends an ‘innocent’ task’s stack – you can almost always catch this before it happens – and I usually find out what the current task is or the current TCB pointer – which is always possible to get. Having to figure out another task? You have to unwind the stack and possibly the scheduler to figure that out. I can’t believe you lost this argument. I would argue the ones that ‘won’ this argument haven’t debugged anything that is ‘real’. Regards, John W.
Again, thanks for your swift reply. My comment was about a potential future issue; FreeRTOS seems to expand in use for continuously higher end devices, with more mem etc. As for the issue on whether to destroy own TCB or other part of memory (not necessarily another task), I think I support the existing approach. Since stack checking is done on context switches, if the TCB is corrupted, the stack check itself may not work. Whereas if it is not corrupted, there is a better chance that vApplicationStackOverflowHook() can run and provide you with valuable info (or rebooting controller) before more harm is done. That requires a proper vApplicationStackOverflowHook() to be present though. If not including stack checking and vApplicationStackOverflowHook(), the arguments may be different.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.