-
Notifications
You must be signed in to change notification settings - Fork 8.2k
lib: os: cbprintf: Add static packaging #32863
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
lib: os: cbprintf: Add static packaging #32863
Conversation
e55ce36 to
a1dbd59
Compare
|
I've been busy with other stuff and avoiding the printf drama. And FWIW this code looks good to me. But... is this solving the wrong problem? As I understand it, the goal behind deferring formatting is mostly to get the output of the log subsystem serialized in a form that does not require formatting on the device at all, right? How much surgery to our printf layer is really appropriate given that as a goal? I was looking at dictionary logging at one point too, and my (somewhat vague) plan was something more like:
I mean, is this code even going to be run on deployed production device? Or are we spending all this effort to come up with a scheme to allow devices to duplicate the production code in some kind of debug mode? |
|
@andyross packaging it's not only about dictionary logging. Current logging scheme is storing all arguments into |
a1dbd59 to
0ddea08
Compare
|
On Thu, 4 Mar 2021, Andy Ross wrote:
How much surgery to our printf layer is really appropriate given that as a goal?
At least with the latest proposal the printing side is completely
unaffected. The idea now is to pre-package a va_list-like buffer that
can be consumed later.
I was looking at dictionary logging at one point too, and my (somewhat
vague) plan was something more like:
1. Put the format string in a separate non-loadable section and give it a unique value at runtime via linker magic
2. Serialize the arguments and the ID in a recoverable way at the point of logging
3. Hand that stuff to an offline python script to figure out
4. Profit
This is almost the case now. The va_list alike chunk only contains
pointers to strings that are known to live in read-only memory, or
packed into the chunk otherwise. So one could retrieve those chunks and
perform the printing offline while omitting the actual printing code
from the device entirely.
|
I do not know enough of this but isn't compiler generating VLA in this case? |
|
@jukkar added following code to hello world: Got following assemby on arm cortex-m4, compiler is able to calculate size of the package: |
4ef69aa to
215d1b8
Compare
215d1b8 to
a70da7f
Compare
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.
Didn't know about that _Generic thing. That's nice! Looks good overall.
You removed static qualifiers in the unit test file.
I'm kind of guessing why you did that, but mentioning the reason explicitly
in the commit log would be best.
I stopped using VA_STACK_ALIGN_LONGLONG, VA_STACK_ALIGN_DOUBLE, etc.
so to use only VA_STACK_ALIGN(type) directly as nothing needs special
exception for those types. Would be a good idea if you did the same to
avoid possible confusion... and reduce the number of code lines.
Finally, the argument length is now final_length / sizeof(int) and
it is stored in the first uint8_t. I'm not sure if your code matches.
Or I didn't recognize that part.
a70da7f to
8614994
Compare
Extracted into separate commit.
Removed.
Code updated. |
|
@pabigot could you take a look? |
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.
Requested changes are elimination of __C_GENERIC and not removing static from internal functions. I don't like reference macro parameters, but won't block on those.
include/sys/cbprintf_internal.h
Outdated
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.
Do we have existing uses of reference parameters in macros? It's not a natural idiom in C.
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.
that was initially mimicking function call which was taking length by reference. I will remove it.
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 #32863 (comment) i'm not sure that i understand now. So since _len is input and output should it be passed by pointer?
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.
I'm saying that people generally won't expect macro parameters to be both input and output, because you can't do that in functions. The way the behavior is accomplished in functions is to accept a pointer. To use a different idiom for in+out parameters in macros just because they're implemented as textual substitution creates an opportunity for confusion.
This is my opinion, I'm not blocking on it.
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.
updated to have inlen and outlen parameters.
include/sys/cbprintf.h
Outdated
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.
It might be better to integrate this into the introduction of the API.
Also __C_GENERIC is not a legal identifier for anybody but the toolchain to use. Even if somebody wants to say "but we are the system so we can do whatever we want" it'll confuse people. Z_C_GENERIC maybe.
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.
It might be better to integrate this into the introduction of the API.
do you mean squashing commits?
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.
yes
tests/unit/cbprintf/main.c
Outdated
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.
I'm really not a fan of reference parameters in macros.
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.
which one? rc is passed by value
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.
No, it's not. The reference to what's declared as int rc is passed to TEST_PRF2 as rc which assigned directly to the argument. So it's essentially what in C++ would be int& rc, a reference parameter.
For parity with functions it should be assigned to as *rc = prf(...) in TEST_PRF2, and passed as &rc.
tests/unit/cbprintf/main.c
Outdated
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.
I really don't like this commit either. We should not have tests/examples that promote contamination of the global namespace with functions that are never referenced outside the translation unit.
If a function's commented out permanently, it should be removed. If it's done during development, ignore the warnings. If it's conditional on build options leave it in the list, and skip on entry when the triggering feature is disabled.
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.
During development commenting a test when running unit test with twister was resulting in errors (it was treat warnings as errors). Do you have suggestion how to handle it there?
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.
If twister doesn't have an option to override the warnings-are-errors behavior, it should be fixed.
-W, --disable-warnings-as-errors
Treat warning conditions as errors
suggests it does, though the help is rather confusing.
8614994 to
ac02c98
Compare
|
@pabigot comments addressed, except #32863 (comment) which needs clarification. |
Extend cbprintf with static packaging. Signed-off-by: Krzysztof Chruscinski <[email protected]>
Extended test suite to test static packaging, too. Signed-off-by: Krzysztof Chruscinski <[email protected]>
Extend test to validate cbprintf static packaging on various platforms. Added more test configurations: complete, nano, long double. Signed-off-by: Krzysztof Chruscinski <[email protected]>
ac02c98 to
eb2e558
Compare
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.
Changes have been made. I'm skeptical of the alignment stuff wonder what happens when people intersperse char arguments with long double arguments, but that isn't new so shouldn't affect this PR.
Hopefully the log rework that motivates all this will make it through review.
|
On Wed, 10 Mar 2021, Peter A. Bigot wrote:
I'm skeptical of the alignment stuff wonder what happens when people
intersperse char arguments with long double arguments, but that isn't
new so shouldn't affect this PR.
It's taken care of. Extra padding is inserted when needed.
Of course this is all architecture dependent so this is explicitly
tested on all of them.
|
Added validation of alignment to cbprintf_package. Error is returned if input buffer is not aligned to the largest argument. Signed-off-by: Krzysztof Chruscinski <[email protected]>
eb2e558 to
06360e3
Compare
Alternative take to #31102, based on #32734.
Staticallymeans that a package (serialized string with arguments) is created as assignment to a buffer. Opposed to runtime package creation with cbprintf_package() where string is analyzed and based on format specifiers a package is created (any transient strings are copied into the package buffer).In principle,
CBPRINTF_STATIC_PACKAGE(buf, &len, "test %d", n)resolves to simple assignments.CBPRINTF_MUST_RUNTIME_PACKAGEis used to determine at compile time if static packaging can be applied.CBPRINTF_STATIC_PACKAGE(NULL, &len, "test %d", n)- null buffer results in length calculationPackage on stack can be created with following code:
Note that static packaging is using
_GenericC11 keyword with fallback to runtime packaging if not available and local suppressing ofpointer-arithwarning ((arg) + 0generates warning if arg isvoid *).