What are the available stack sizes?

How much memory is available for the stack when using:

  • Timer
  • Thread
    Is that documented somewhere?

Good question @jernstlun — stack sizes are not documented anywhere. I just created docs issue 579 to correct this.

Timer uses 84 bytes of heap, which you can find by running System.freeMemory() before and after allocation. I don’t know about stack usage, however, @BDub told me he can create 1000 timers no problem, so their stack usage is minimal.

Each thread has its own stack. Thread has a stack_size parameter (see the thread class header file) that defaults to 3KB. As far as what’s the max stack size you could throw at your own Thread, I’d recommend trying to break it and reporting back here.

On :particle: Wi-Fi devices like the Photon and P1, WICED creates multiple threads that have their own stacks, including the “application thread” that has a 6144 byte stack.

Our default stack size is 2KB.

HTH!

3 Likes

Thanks, @zachary!

What about Timer callbacks? Poking around the code, it seems – but I’m not certain – that Particle Timers map pretty closely to a similar FreeRTOS structure, but I’m getting lost attempting to figure out just what thread exactly is invoking the callbacks and what its stack size might be.

I presume if I have a lot of Timers, the callbacks are all invoked in sequence from the same thread?

(Context, and I’m sure you guessed, is that I’m attempting to figure out some strange stability issues, and insufficient stack size of something is one of the leading contenders for a theory …)

I am pretty sure software timers use a 1024 byte stack. And all timers are queued are processed out of a single thread.

Another source of instability with software timers is a lack of thread safety between your timer callback and the main application loop thread when using a shared resource. You need to manually write that into your code; it’s not generally handled automatically.

The right pattern is to keep the timer callbacks absolutely as minimal as possible, simply setting a flag which is then acted upon in the main loop().

From the Software Timers section of the docs:

Please note that Software Timers are "chained" and will be serviced sequentially when several timers trigger simultaneously, thus requiring special consideration when writing callback functions.

and

The timer callback is similar to an interrupt - it shouldn't block. However, it is less restrictive than an interrupt. If the code does block, the system will not crash - the only consequence is that other software timers that should have triggered will be delayed until the blocking timer callback function returns.

@rickkas7 Any idea where you got the 1024 number? I see Timer calls os_timer_create which calls xTimerCreate which is a FreeRTOS function, but I couldn't find the stack size from there.

I might be mistaken, but I think the timer thread is started here:

And configTIMER_TASK_STACK_DEPTH is defined here:

The number of Software Timers is limited to 10. From the docs:

Software Timers provide a way to have timed actions in your program. FreeRTOS provides the ability to have up to 10 Software Timers at a time with a minimum resolution of 1 millisecond.

I forgot to ask about callbacks from Particle.subscribe. What thread is that and what might its stack size be?

Subscription handlers are run out of the main loop/application thread so 6144 bytes.

3 Likes

So the main thread has a stack of only 6144B? Considering the total RAM size of 128KB, isn’t it kinda low?

Is there a way to increase it? I’m assuming it is set via WICED_DEFAULT_APPLICATION_STACK_SIZE, but I don’t see that variable used anywhere.

If you are not programming too stack heavy, I'd say No.
You have to consider there may be other threads that need some stack space, you want some global and heap memory too, so the stack shouldn't be oversized.

@andrey, thought the total RAM is 128K, some of that is used by FreeRTOS and the system firmware leaving about 80K to the user.

It so happens that I’m heavy on stack usage. Is there a way to increase application’s stack size (maybe at the cost of heap size)?

2 Likes

Resurrecting this thread after a year and a half (hope that’s okay?) because I have this exact problem as well. I have several variables which I want to scope appropriately to the task, and not make them into globals. They’re quite large, and architecturally speaking I’d rather they tightly stayed contained in the application task.