Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Software tasks and the stack #927

Open
TomCrypto opened this issue Apr 24, 2024 · 1 comment
Open

Software tasks and the stack #927

TomCrypto opened this issue Apr 24, 2024 · 1 comment

Comments

@TomCrypto
Copy link

I noticed RTIC was recently updated to change the way software tasks are stored. Previously, they were stored in statics, which required the ability to name them (hence the use of TAIT requiring nightly). They are now stored on the stack in the entry point, which is never returned from, making them essentially static for all intents and purposes but without the need to name them. Presumably this is what has allowed RTIC to work on stable Rust.

I've faced some issues with this change. First, this change completely and hopelessly breaks the flip-link mechanism, which I was using, since the software tasks will almost certainly immediately blow the reserved stack area in many cases. Yes, more memory can be reserved to make space for them, but it's difficult/tedious to know how much, the ELF cannot even be inspected for this information since the software tasks no longer have symbols.

This means continually running into stack overflows during development and having to repeatedly bump up the stack size, or getting fed up of doing that and reserving an absurd amount of stack space during development, which may not always be possible depending on available memory.


So the alternative is to use the default stack-grows-down, statics-grow-up setup. This works, but is not ideal because it's not possible to know when the stack becomes too small after task allocation. This is not specific to RTIC, but RTIC makes it worse because the generated futures have sizes that continually vary unpredictably during development depending on how code is written, how much is borrowed across yield points, and so on.

I saw that RTIC has a check for this, but quite honestly I'm not sure what this is solving - it will still continue even if e.g. there's only 600 bytes of stack left after all the tasks have been allocated, likely causing hard faults at some undefined point later in the program's execution. And this happens all the time during development when you don't have much memory to spare for a given program and target device. Perhaps it should check for at least N free bytes on the stack after allocation, though I don't know how you'd make N configurable.


In short, the current behavior has very poor ergonomics when there isn't much available spare memory.

In contrast, the previous approach where software tasks were stored in statics had the advantage that it was compatible with any stack layout, and had the secondary side effect that it was easy to inspect the size of the tasks since they each had a symbol in BSS, making it easy to tell how much of it was your own stuff and how much of it was related to software tasks. And if you wanted to reserve a fixed stack size, you could do that, and the build would just fail. Now it will just crash... sometimes.

Would it be possible to improve how RTIC software tasks interact with the stack?

@korken89
Copy link
Collaborator

korken89 commented May 8, 2024

Hi,

Could you elaborate on how the behavior is different from before?
If we allocate the tasks statically or on the stack of main will give the same end result. If you use flip-link you will eventually have the stack grow outside available memory and you will get a hardfault with a memory fault (invalid address).
This behavior was tested to be the same before and after the move to stable and using mains stack as an allocator.

I do however agree that you cannot get the info about the amount of RAM used to allocate the executors.
We added this API, which you can query to see how much RAM was used. It's better than nothing, but indeed not as direct as before.

https://github.com/rtic-rs/rtic/blob/master/rtic-macros/src/codegen/module.rs#L21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants