-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[PoC, RFC] Don't use <stdio.h>
in RIOT
#13710
Conversation
- Added functions to fill columns with arbitrary chars - Added functions to fill on the right side (left-aligned columns) - Added functions to print with leading zeros
- Reduces ROM requirements by ~7K for newlib (unless printf() is used by other stuff) - Works fine for threads with smalls stacks
- Reduces ROM requirements (when stdio is not pulled in by other stuff) by about 7K for newlib - Works fine even for threads with tiny stacks
I like |
To some degree that would be possible. But it does not support stuff like Btw: We could also use something like |
I'd trade these 'luxury' printf features for smaller code any time 😉 |
I have a printff implementation using fmt as backend, which is also a lot smaller and uses a lot less stack. In fact, I got a branch that adds a homegrown replacement C library. But comparing it's codesize with pico libc made me put it on hold. picolibs has a much smaller stdio implementation. We should aim at switching to that first, then evaluate libc replacements against that. |
Please note that the idea proposed here is "getting rid of (*) That is everywhere in That said: If picolib's |
I think picolibc is actually using printf from AVR libc... |
Ok. ;) |
Hmm, maybe this idea would be something for discussion in the next VMA. I think it is somewhat radical - especially in the context that RIOT wants to provide a POSIX like look and feel with a high degree of POSIX compatibility. But during a discussion with potential users outside of the academic sphere it became obvious that full MISRA C compliance is simply not optional for many actors in the industry. And enabling a boarder user base might be just the argument required to sell such radical idea. (Note: I don't want to indicate that enabling users to not use |
many uses of the DEBUG would be simplified to a string and therefor not require a fmt parser, if it just adds a line number and file name by default. this could further improve the situation if a second makro is defined that not prints the error message which would remove it from the binary. |
With picolibc I don't know if there is much to gain still from using |
printf might need a larger stack. Even if not the stack of a thread is enlarged indirectly by making it able to debug print using the newlibc printf. |
This sounds like a worthy change, but also a big effort to do system-wide. Is there a subset of this that we could get usable earlier and migrate where it matters most? Point in case: #16448 (comment) runs into stack overflows in DEVHELP mode in the panic handler, and can easily be moved to puts-style prints rather than printf ones -- but starts them through LOG_ERROR. Would it make sense, for example, to string-only log functions for these calling sites, while retaining printf (with all its stack usage) for the general case / while waiting for the full solution? |
Certainly. All those panic handlers would be good candidates. But I think we need first come to the consensus that we really do not want to ban use of stdio from RIOT except for debugging. I think there is a consensus that newlib's stdio is performing exceptionally poor in terms of both stack usage and ROM requirements (even the nano variant) - which is quite surprising considering its lack of features (e.g. no %lld / %llu). But there are two alternative solutions to that:
|
On Mon, May 10, 2021 at 02:28:26AM -0700, Marian Buschsieweke wrote:
> Is there a subset of this that we could get usable earlier and migrate where it matters most?
Certainly. All those panic handlers would be good candidates.
But I think we need first come to the consensus that we really do not
want to ban use of stdio from RIOT except for debugging.
Do we need large-scale consensus building on the future of printf-style
statements to introduce a way for critical (stacksize-wise) components
to do without whatever we do about printf being hard on resources?
(And when was this ever about banning stdio in full? AIU this is more
about providing better tools than what is in stdio, or using the good
tools that exist where we don't need full printf).
…--
To use raw power is to make yourself infinitely vulnerable to greater powers.
-- Bene Gesserit axiom
|
Check the PR title and description ;-) |
(Emphasis mine.) I understood this combination to indicate a "The PoC shows we could go completely stdio-free but it's more an exercise to find the pain points" -- or was there just a stray "not" in #13710 (comment) ? |
Disclaimer
This PR contains a bunch of commits that would be better split into separate PR. But this PR is not indented to be merged nor to be reviewed in-depth, but rather to demonstrate the feasibility of an idea. If the general idea is accepted to be worth pursuing, this PR will be split up into multiple PRs to allow efficient reviewing.
BEWARE: This is almost completely untested.
Contribution description
This PR replaces the use of
<stdio.h>
within some portions of RIOT withsys/fmt
:print_...()
family of functions directlyDEBUG()
andLOG_DEBUG()
/LOG_INFO()
/... cannot simply be replaced, as the API is closely coupled toprintf()
printf_nano()
function is added as modulefmt_stdio
. This function implements a small subset of theprintf()
format specifiers using theprint_...
functions.printf_nano()
should be enough for our debugging and logging requirements and is used by default forDEBUG()
andLOG_...()
by defaultWhy?
Code Size
With master:
With this PR:
Note: There is likely still some room for further improvement. This PR is just a quickly written proof of concept.
Stack Requirements
The newlibs implementation of
<stdio.h>
uses significant amounts of stack.DEBUG()
to prevent stack overflows. With a lightweight alternative like theprintf_nano()
provided here should often without having to increase the stack size of driver threads or at least with increasing the stack only a littleprintf()
is used, which results in significant stack allocation for that handler. Usingprint_...()
provided byfmt.h
should result reducing that stack. (BUT: This has not been done in this PR, as the actual stack requirements need to be evaluated with care, as different compilers might produce binaries with different stack requirements.)Huge Complexity of the API in
<stdio.h>
<stdio.h>
MISRA C Compliance
<stdio.h>
should not be used in production code"core
,sys
, anddrivers
would allow users to decide for themselves if they want to follow this MISRA C rule.Testing procedure
Doesn't apply (yet). Detailed testing descriptions will be provided for the individual PRs split out of this, if the general approach is agreed upon.
Issues/PRs references