rtel wrote on Monday, December 23, 2013:
Software has many attributes, and trying to draw a comparison by looking at just one while ignoring the others just doesn’t work.
For example, code size, testability, correctness, robustness, code reuse, design, etc. Engineering is almost by definition about finding the best compromise because you cannot optimise all attributes at once - you can only trade off by optimising one attribute at the expense of another.
FreeRTOS has just one central primitive that is re-used to provide lots of functionality - meaning that central primitive extremely well tested and robust. It also allows FreeRTOS semaphores to be implemented with practically no impact on code size at the expense of a few structure members being redundant when the structure happens to represent a semaphore. The semaphores include all the event management, including a highly efficient and ordered linked list of tasks that are blocked on the semaphore waiting to obtain the semaphore, a highly efficient and ordered linked list of tasks that are blocked on the semaphore waiting to give the semaphore, a count of the number of semaphores available (where the semaphore is of counting type), lock variables that allow the semaphore to be used from within interrupts and tasks simultaneously without causing corruption, plus some optional variables used for tracing, etc. Therefore, when you say CoOS uses 16 bytes, I doubt very much you are comparing like for like, as there cannot be all that functionality in the semaphore structure, so presumably either the functionality is not the same or the data associated with the functionality is simply somewhere else. Many OSes will allocated separate event management structures.
The above description of the FreeRTOS semaphore, with the optional tracing structure members, I have just measured to take 80 bytes on a 32-bit architecture, not the >100 bytes you have measured, so I don’t know what it is you are measuring. Many it depends on the memory allocator used as some store some extra information that is not visible to the application writer.
Who else (except task itself) may use so many stack? What about scheduler?
How much stack your application uses is completely dependent on your application, the compiler you are using, and the optimisation setting of the compiler. The scheduler stores the task context on the task’s stack when the task is not running - but that is a fixed size set by the architecture, has to be stored somewhere (if it wasn’t on the stack it would be somewhere else), and will take up less space than most of your function call stacks anyway. Interrupts do not use any task stack, they have their own stack, and in fact re-use the stack that was originally used by the main() function to ensure no RAM is lost.
Ultimately, there are lots of RTOSes available, you have to choose the one that best suites you, which may or may not be FreeRTOS. We would like you to select FreeRTOS because we are extremely proud of it, but financially it does not make a difference to us either way. Of course, technical attributes are only a subset of the attributes to consider when making your selection.