Static objects initialization

anonymous wrote on Wednesday, April 29, 2009:

Each time I see people asking how many tasks they can create, I wonder whether it would be possible to statically initialize all the objects in FreeRTOS at compilation time.

It would be possible to declare a task as

  TASK(pvCreatedTask, pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority);

and register it with the scheduler using

  xTaskRegister(pvCreatedTask);

instead of calling xTaskCreate. xTaskRegister would do the classical initialization in the existing pre-allocated space.

Note that there is no obligation to declare the TASK macro with all the parameters I used; keeping pvCreatedTask and usStackDepth could be enough information for the macro.

This way, once the code compiles and links, you *know* for sure that you get enough space in memory for your task to be created (provided you got the stack size right), and xTaskRegister could not fail unless the task has already been registered. No dynamic allocation would be needed at scheduler start time (as even the idle task could be created this way), and the task name could even be kept in read-only memory (it could be copied onto the newly allocated stack space if a task is dynamically created using xTaskCreate, which I don’t propose to remove of course).

Doing the same with every kind of objects (queues, semaphores, mutexes) would probably remove every need of dynamic allocation in many use cases. If it became the preferred way of creating objects, we would not see those questions anymore (their frequency hints that this is a problem for many people).

rtel wrote on Wednesday, April 29, 2009:

In SafeRTOS everything is statically allocated.  The queue/task/semaphore creation functions have been extended to include a pointer to the buffer to be used to hold the queue/task/semaphore structures and data.

It works well, and removes the problems associated with dynamic allocation for safety systems.  I would say however it is more complex as you have to allocate and dimension the buffers manually, and the create functions have an extra parameter.

Regards.

anonymous wrote on Wednesday, April 29, 2009:

I was thinking more of something like (totally untested)

#define TASK(name_handle, stack_size)     
static struct {
   [Common task fields there as expected by the scheduler, including list structures]
   portBASE_TYPE stack[stack_size];
   portBASE_TYPE end_of_stack[0]; 
  } name_handle # _STATIC;   
xTaskHandle name_handle = (xTaskHandle *) &name_handle # _STATIC

#define xTaskRegister(name_handle, pvTaskCode, pcName, pvParameters, uxPriority)
   prvTaskRegister(name_handle,
              &name_handle # _STATIC.stack,
              &name_handle # _STATIC.end_of_stack, 
              pvTaskCode, pcName, pvParameters, uxPriority)

which doesn’t require to separately reserve buffers and gives to prvTaskRegister all the information it needs to properly initialize the stack (its position and size).

anonymous wrote on Wednesday, April 29, 2009:

(this may be easier to read on http://paste.factorcode.org/paste?id=625 which preserved formatting)