[En-Nut-Discussion] stack size

Nathan Moore nategoose at gmail.com
Wed Mar 26 23:32:30 CET 2008


>
> The stack space used is the sum of
> a) - local variables
> b) - stack space needed by the compiler in case of complex statements (in
> case intermediate registers need to get saved (I assume!)
> c) - stack space needed by functions called by the API functions (and now
> the whole thing starts over...)
> d) - stack space needed by interrupt routines
> e) - stack space used by clib (or other) library functions


Don't forget return pointers.

>
>
> This is dynamic, i.e. it can't be predicted. (at least I don't know how)


As long as you don't use recursion, use alloca or dynamically sized arrays,
dynamically build devices that depend
on other devices that depend on other devices...
or use some really weird coding (essentially the device stacking again) it's
actually deterministic for any given build
if you account for the most stack hungry ISR, but it's really hard to
calculate.  Devices with function pointers are the
hardest thing to figure out.


>
>
> I guess what would be needed are
>
> - either a compiler which analyzes the possible flows thru the various API
> functions to build up the layout of a "dummy stack". This would cover a)
> and
> c)
>
> - or a little hack to use NutHeapAllocClear instead of NutHeapAlloc when
> allocating the stack of a new thread and then have a number of controlled
> API function calls with an "how much did the "cleared" content of the
> stack
> change during the function call.
>
> - or finding an avr simulator which has functions (or hooks) to be able to
> analyze how the stackpointer changes during a certain flow thru the
> program


If you can temporarily spare the memory you could do either the alloc clear
or set to another value
and also oversize the stacks at thread creation.  You'd have to really put
the build through it's paces
to try to achieve the highest stack usage possible.

Another thing you could do is have a macro:
#ifdnef CHECKTHESTACK
#define ASSERT_STACK_INTEGRITY()
#else
#define ASSERT_STACK_INTEGRITY()    do { \
      ... \
    } while ()
#endif // CHECKTHESTACK
and place this macro at the top of every function.  This macro could be as
simple as
        push tmp_reg
        push -1
        pop tmp_reg
        pop tmp_reg
which would allow you to inspect the stack in a memory dump, or you could
compare
the current stack pointer to the value as calculated by the allocated stack
size for the
current thread and the bottom of the stack for the current thread (I think
this can be
calculated with stuff in current_thread??) and then maybe some stack
unwinding could be
done and an error could be reported or recorded including which thread was
current and
what functions were called when it happened.
That's pretty big ambitious, though.

Anyway, I'd just wondered if anyone had thought up anything any better or
there were any
recommendation for each API function's stack needs.

Nathan



More information about the En-Nut-Discussion mailing list