-
Notifications
You must be signed in to change notification settings - Fork 109
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
boards: Set stack size from within apps #180
Conversation
I have to say that I find this quite inconvenient to use. Firstly, it depends on convention and it is not clear why a properly compiling app fails because of not enough stack. Secondly, I don't want to bother the user with such details.
|
This is the exact problem we have today. I usually test with a larger stack size as I have seen multiple times where the default 2K stack isn't large enough.
They already have to think about the stack. To fit apps on the HiFive1 you need to shrink the stack size, but to run complex examples you need to increase it. There is no one size fits all size. Do we really want to spend 2K of stack to blink LEDs? That seems a little big and makes the example too big to fit on the HiFive1. On top of that we are also starting to see example apps that need stack sizes larger then 2048. What then? Every app has to have a 3K stack just for one large example? I tried a few different ways and this is the least fragile. I can't find anyway to use environment variables in a linker script. I tried using sed to edit the linker script, but that doesn't really get you anything. How would Rust macros be used to edit the linker script? The stack usage changes per app, not per board so it makes more sense to have an app set it. It's now clearly set out for every app. If start with the |
I think we should have per-app linker scripts that define STACK_SIZE then #include the per-board linker script. Unfortunately, because all the examples live in a single directory, I think they need to share a linker script. I think we should either move larger examples out to their own directory or we should optimize until stack usage isn't a problem for any of the examples. |
I don't see how a linker script per app is any easier. It just means there is another place to edit values. Stack usage is always going to be somewhat of a problem though. It will take less stack to blink an LED then to do complex computation and send it over Bluetooth. A per app stack avoids wasting space on the simpler apps. |
I see to ways here:
I think 2) is trivial, 1) is more involved but would prepare the "slots" approach for relocation if it is still the plan to use it. |
This sounds to me that the stack for the examples should be limited per board for now. |
There are some users that have to do it. On the nrf52dk I never had stack issues and I think users with more powerful boards will never think about stack sizes. |
That's how I think about configuration: If there's a default value - don't show it. Configuration is much more maintainable when you see only the non-default values. |
This is exactly what I was thinking about in the past. There are some great templating engines. Why not use one of them in the |
Sorry to be late to this, but I think libtock-c already does what you want? The Makefile picks up the environment variable From some quick googling, it looks like the llvm linker also supports the |
@ppannuto: I think this depends on rust-lang/cargo#7811. |
So the problem with A macro has the same problem. There isn't really a way to pass a macro from an app to the linker script. @torfmaster you are right that large boards won't really have an issue. You can just set the stack higher then you need and not worry about it. It is wasting space, but maybe that doesn't matter. The problem is there are smaller boards where this is a problem. The MPU errors aren't always obvious. Especially on RISC-V boards without PMP (the MPU equivalent) like the HiFive1 revA. OpenTitan doesn't have working PMP implementation today, so there is no reporting if you overgrow the stack. |
You can just create an array as you did using a proc macro without touching the linker script. Inside you can read whatever you like: variables, files, ... I don't want to imply that I prefer this solution. But I prefer it over putting arrays into the examples for non-obvious reasons. Edit: typo |
Ok, I created an issue to track this: #181 I'll leave the macro or linker script generation up to you as I don't see how it would work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that apps here don't have an associated makefile, this seems like a pretty reasonable method for setting the stack size.
@alistair23: Here's one issue I found while implementing the dynamic linker script generation. How do you plan to pass the stack size used in your apps to elf2tab? |
I see, you are reading it from the artifact. I'm leaving this comment here for reference. |
When I forget to create a stack buffer inside an example I get the following error message
plus the usage of elf2tab. I think this should be replaced by an error message explaining what failed and why. |
How would an error message be generated? |
I happen to be a big fan of this change because of how it causes the segments to be created in the ELF. On master:
With this PR and the following diff: diff --git a/layout_generic.ld b/layout_generic.ld
index 7536a3b..c5b5130 100644
--- a/layout_generic.ld
+++ b/layout_generic.ld
@@ -85,7 +85,7 @@ SECTIONS {
} > FLASH =0xFF
/* Application stack */
- .stack (NOLOAD) :
+ .stack :
{
_sstack = .;
KEEP(*(.stack_buffer))
When the stack has a section mapped to it (as in this PR), and is not marked as no load, we get a RW segment at address With the stack marked With the stack only set by the |
After more digging, the incompatibilities between llvm and gcc make even having this PR merged not enough to do automatic RAM address detection without a bit of guesswork and heuristics (at least as far as I can tell). I still think that we need to be able to set the stack on a per-app basis, however. |
Ping! This is an even bigger problem today now that we have more complex examples such as CTAP. This has been reviewed by someone and ACKed by a few people. If I rebase it can it be merged? |
I'm strictly against this solution as I already mentioned. It makes the library hard to maintain for no good reason. |
I'm not enthused about the mechanism this PR uses to specify stack sizes (I think it is really ugly), but I recognize that there is a problem here and this is the only PR that offers a solution. #184 allows the stack size to be set via environment variable -- which I prefer in general -- but that doesn't work for libtock-rs' examples. As such, I think this should be merged despite its uglyness. |
I'm for merging this if it is rebased. |
Agreed that it's not the prettiest, but it also matches how we set stack size for boards in the kernel, so there's some consistency there at least. Biggest win for me is that changing stack size used to require changing things in two places (linker script and flash script argument to elf2tab), but now there's just one authoritative stack size location. I think this is a go for me for now, with the understanding that we're open to a another solution if/when one presents itself later. |
As a user I wouldn't use the library anymore if I had to manipulate such low-level-details in such a way - it feels to much like C. As I said: we should create a separate CTAP crate and use a feasible solution for setting the stack size - but if you want to make this library unsable for users exept some few people from WDC and google - go for it. |
Your concern is that the following 4 lines are too low-level to be in an application, correct?
Other than a stylistic objection, do you have a reason why this solution is unworkable? If not, then "unusable for users except some few people from WDC and google" is an exaggeration. This PR isn't a code style improvement, it is a fix to allow us to continue developing and testing |
I'm all agreed it's ugly. If someone has a nice way to improve it please send a patch and I'll happily review it. I have rebased this PR, it's failing again from the OT boot ROM being out of date. Just waiting on my Tock PR to be merged: tock/tock#2151 |
5c724d9
to
62d5979
Compare
https://github.com/hudson-ayers/libtock-rs/tree/stack-setup-2 contains a patch that maintains a default buffer size, but lets apps that want a different size than the default change it by passing the desired stack size as an argument to E.g. most apps stay exactly as they are today, but if an app wants a bigger stack size it uses Thoughts? |
That works for me. |
I'm going to see if I can generate that symbol from a |
Yeah, I went the procedural macro approach just because we already are using one to declare main, and it seemed sensible that setting a stack size be associated with declaring main - each can only be done once. Also this prevents having to add any new code to apps that want to keep a default. |
I updated my branch so the syntax is now |
Yeah it makes sense for |
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Stack size isn't board specific, but more app specific. So let's set the stack size from within apps. This follows what TockOS does and sets a buffer for the stack. We then parse that buffer when running elf2tab to use that value. Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
62d5979
to
dcdfe18
Compare
Gotcha. If we have a |
That seems like it should be possible. I just opened #244 which demonstrates the |
I disagree that this is necessary to actually develop |
Is there a reason for that? Declarative macros have the disadvantage that
Do they have advantages at all? |
From a design perspective The other objections is that this is error prone: alignment is not checked, error messages are not really helpful if you forget to specify the link section. It's exactly opposed to the Rust philosophy: If it compiles - it works. Now you would have to copy and paste the examples and fiddle in the code. If something doesn't work you have to search for the error in hundrets of lines of Makefiles and bash scripts - which are untested and ill-documented - exactly as in C embedded development. |
And I still don't understand why we don't choose a solution like #184. I know it is a little bit of work to be done but I also took a lot a work of me in my spare time with that without beeing interested in the topic of setting stack sizes because I care about the quality of the library. My forecast is: in 6 months we'll be again discussion about workarounds resulting from the limitations of "examples" in Rust crates and we'll have another hacky workaround to fix that instead of finally making |
I don't speak for Johnathan, but I can think of a few. Declarative macros are hygenic, and procedural macros are not. Procedural macros have some security concerns: https://doc.rust-lang.org/reference/procedural-macros.html. Procedural macros require the use of crates not contained in std.
For this PR as it stands I somewhat see this perspective, but for #244 , for instance, I think that asking novice users to include
This seems pretty easily resolvable with an additional assert in the linker. The alignment is already checked at compile time, we could add a check that the
The code is linked at compile time, so an assertion in
The biggest issue I see with #184 is that it does not allow setting a stack size for a particular example, something we support in
I'm a little confused as to what you are asking for here; do you think that no examples should live in the main libtock-rs crate, and each example should live in its own crate? |
Those crates ( We won't be using futures in the long run so we eventually won't have the |
You mean, |
I intend to add some futures support to |
244: Make binaries specify their stack size using a new stack_size!{} macro. r=alistair23 a=jrvanwhy Prior to this PR, it was not possible for binaries to specify their own stack size. libtock-rs had a hardcoded stack size of 2KiB. This is an alternative to #180, which had some pushback for requiring `libtock-rs`'s users to write low-level code. Co-authored-by: Johnathan Van Why <jrvanwhy@google.com>
Closing as this was addressed by: #244 |
Stack size isn't board specific, but more app specific. So let's set the
stack size from within apps.
This follows what TockOS does and sets a buffer for the stack. We then
parse that buffer when running elf2tab to use that value.
Signed-off-by: Alistair Francis alistair.francis@wdc.com