cvra / platform-abstraction

Platform abstraction layer for microcontrollers
3 stars 6 forks source link

Design a threading API #9

Closed antoinealb closed 9 years ago

antoinealb commented 10 years ago

So, now that mutex and semaphores are more or less sorted out, let's talk about threading. For me the threading API involves quite a few design decisions :

  1. How are the stack for each task allocated ? Are they all of the same size ? Personally I suggest a variable stack size, allocated on the heap using malloc(), although there may be problem on the ARM targets I am not aware of.
  2. Can a task function return ? In uC/OS-III this is not possible : one task has to call OSTaskDelete(OS_PRIO_SELF); before returning. Do we want a wrapper around tasks to do this for us ? I would say yes.
  3. Priorities. Do we stick with native priorities or roll our own that we convert to target system's ? I would suggest sticking with the uc/OS-III priority system and if we meet another RTOS with another priority system we will decide at that point.
  4. Suspending and resuming of tasks : any use case for us ?
msplr commented 10 years ago

How are the stack for each task allocated ? Are they all of the same size ? Personally I suggest a variable stack size, allocated on the heap using malloc(), although there may be problem on the ARM targets I am not aware of.

Allocating the task's stack shouldn't be a problem on ARM Cortex-M. (You would probably just have to ensure alignment) However, I wouldn't pack the stack into the heap, but rather statically allocate all the stacks in a separate memory section. (a stackoverflow corrupting malloc's data structures or data allocated next to it) Why allocate them dynamically? I assume most threads will be running all the time anyway.

antoinealb commented 10 years ago

Why allocate them dynamically? I assume most threads will be running all the time anyway.

That's not sure : consider the case of a debug TCP shell : you want to spawn one thread per incoming connection to handle multiple clients.

msplr commented 10 years ago

That's not sure : consider the case of a debug TCP shell : you want to spawn one thread per incoming connection to handle multiple clients.

ok, in this case it makes sense, but I wouldn't do it with all the stacks.

antoinealb commented 10 years ago

I would prefer if the stack could be allocated wherever we wanted them, heap or special section.

We will probably need some wrapper around the task stack type too, to use the stack overflow detection function and such.

pierluca commented 10 years ago

With regard to point 3, how much effort is entailed by the development of a very thin wrapper around the uC/OS-III priority system? Comparatively, how much of the code base should we change if the underlying priority system changes?

antoinealb commented 10 years ago

uc/OS-III priority system will not change for another 5+ year probably. The ony "real" case would be if we change our RTOS but it still will be very easy to change priorities in the application.

antoinealb commented 10 years ago

I am actually working on the threading API and would like to know if there is a real use case for variable stack sizes for optimization purpose or if we will always use the same stack size (easier implementation).

msplr commented 10 years ago

The required stack sizes greatly will vary between threads. Therefore we definitely want to have different stack sizes.

Stapelzeiger commented 10 years ago

We don't have an external RAM like on the FPGA board, so space is very limited. I think we need variable stack sizes. Also we should allocate stacks in a separate memory on the master (STM32F4) board for performance.

antoinealb commented 10 years ago

Separate memory

What do you mean, like second adress bus or ?

Space is limited

Fuu, no more Lua/Python.

But ok, I will be working on an implementation allowing static variable-sized stacks.

Stapelzeiger commented 10 years ago

Yes, there is a "core coupled memory" that is separate. If the stacks are in that memory, DMA transfers shouldn't affect performance.

antoinealb commented 10 years ago

You can do it with a linker section ?

Stapelzeiger commented 10 years ago

yes, you just have to add __attribute__ ((section (".ccm"))) to your variable declaration and define the .ccm section start & end in the linker script. (this works for uninitialized data. if we need to initialize it at boot we have do it manually, by defining a lma&vma and copying the data before we call main)

antoinealb commented 10 years ago

Mmmm, I see. Then we should probably have some kind of macro / defines to statically allocate a stack of a given stack, put it in correct memory, etc.

Stapelzeiger commented 10 years ago

This might be a good idea.

pierluca commented 10 years ago

I'm useless here, not enough experience with embedded systems. I'll go with whatever you judge appropriate :)