-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
logging: Prevent multiple arguments evaluation (take 2) #42686
logging: Prevent multiple arguments evaluation (take 2) #42686
Conversation
@nordic-krch we also had issues with the previous attempt on XCC, @dcpleung can provide the details. |
Actually, @MaureenHelm found the issue first. The issue is that XCC complains: |
d2b707b
to
f71fce0
Compare
Added guard similar to one in cbprintf. For GCC < 4.9 and clang < 3.8 runtime packaging is used always and preprocessor cuts path with __auto_type and _Generic. |
f71fce0
to
0d314bf
Compare
include/logging/log_msg2.h
Outdated
#ifndef CONFIG_LOG2_ALWAYS_RUNTIME | ||
#if !defined(__cplusplus) && \ | ||
!(((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40900) || \ | ||
((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 30800)) |
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.
Maybe put this in a #define ?
#if condition_for_supporting_autotype
#define AUTO_TYPE_IS_SUPPORTED
#endif
Would make the rest of the logic simpler, and potentially be useful if someone else wanted to know if autotype is supported.
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.
are there any way we could detect if this is supported before build time ?
For example checking compiler version in CMake or testing the compiler (I'm not aware of any compiler flags related to this feature, so this will most likely not be possible).
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.
not sure about compile time, but i rephrased this define to fixed #42686 (comment) same time.
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.
placed comment here: #42686 (comment)
comments to comments easily gets lost in history threads.
include/logging/log_msg2.h
Outdated
*/ | ||
#define Z_LOG_LOCAL_ARG_NAME(idx, arg) COND_CODE_0(idx, (arg), (_v##idx)) | ||
|
||
/* Create local variable from input variable (expect first (fmt) argument). */ |
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.
/* Create local variable from input variable (expect first (fmt) argument). */ | |
/* Create local variable from input variable (except for the first (fmt) argument). */ |
include/logging/log_msg2.h
Outdated
COND_CODE_0(idx, (), (auto Z_LOG_LOCAL_ARG_NAME(idx, arg) = (arg) + 0)) | ||
#else | ||
#define Z_LOG_LOCAL_ARG_CREATE(idx, arg) \ | ||
COND_CODE_0(idx, (), (__auto_type Z_LOG_LOCAL_ARG_NAME(idx, arg) = (arg) + 0)) |
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.
Can we have a define that evaluates to either auto or __auto_type so this is simplified ?
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.
Done, Setting Z_AUTO_TYPE
define to auto
in cpp and __auto_type
if c (and supported).
include/logging/log_msg2.h
Outdated
|
||
/* First level of processing creates stack variables to be passed for further processing. | ||
* This is done to prevent multiple evaluations of input arguments (in case argument | ||
* evaluation has consequences, e.g. it is a function call). |
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.
* evaluation has consequences, e.g. it is a function call). | |
* evaluation has side effects, e.g. it is a non-pure function call). |
@@ -0,0 +1,288 @@ | |||
/* |
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.
Suffix should be .h, not .inc.
This makes it easier for tools and humans to understand what kind of file it is.
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.
there is a pattern, first started in tests/unit/util
to name if test.inc
and this is forth test that do that. I would keep it as is for consistency.
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.
fair enough
54fe62f
to
046c109
Compare
include/logging/log_msg2.h
Outdated
((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 30800) | ||
#define Z_AUTO_TYPE __auto_type | ||
#else | ||
#error "Compiler lacks support for __auto_type. Enable CONFIG_LOG2_ALWAYS_RUNTIME." |
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.
should be
#ifndef CONFIG_LOG2_ALWAYS_RUNTIME
#error
#endif
right?
I see that below in this file we are checking if this define is set, so I assume it is not always unset.
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.
my bad. fixed.
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.
"move fast and break things" ;)
looks like a good job overall, at least the parts I was able
to understand.
046c109
to
41123c4
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.
Please use the features of CMake instead of hacks like including test.inc
in to main files that are named just for the sole purposes of having them compiled with different compilers.
target_sources_ifdef(CONFIG_CPLUSPLUS app PRIVATE src/maincxx.cxx) | ||
|
||
target_sources_ifndef(CONFIG_CPLUSPLUS app PRIVATE src/main.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.
actually, because maincxx.cxx
and main.c
are identical and including the same file, so a much better approach is to request CMake to compile main.c
using the C++ compiler, like this:
target_sources_ifdef(CONFIG_CPLUSPLUS app PRIVATE src/maincxx.cxx) | |
target_sources_ifndef(CONFIG_CPLUSPLUS app PRIVATE src/main.c) | |
target_sources(app PRIVATE src/main.c) | |
if(CONFIG_CPLUSPLUS) | |
# Feel free to add a good comment here. | |
set_source_files_properties(src/main.c PROPERTIES LANGUAGE CXX) | |
endif() |
and then remove maincxx.cxx
as well as test.inc
.
Have just a single main.c
file.
Cleaning of other places using test.inc
can be done in seperate PR.
include/logging/log_msg2.h
Outdated
#define Z_AUTO_TYPE __auto_type | ||
#else | ||
#ifndef CONFIG_LOG2_ALWAYS_RUNTIME | ||
#error "Compiler lacks support for __auto_type. Enable CONFIG_LOG2_ALWAYS_RUNTIME." |
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.
Could we check configure time:
#42686 (comment)
For example checking compiler version in CMake
This can be done with: https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_VERSION.html which is supported for gcc and llvm.
That way we may detect this BEFORE compilation.
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 way we can inform user earlier that there is a configuration issue that must be fixed.
Always use runtime packaging in immediate mode. Removing attempt to package on stack if possible. It would be done only to speed up logging but that is not a requirement in immediate mode where packaging time is fractional compared to backend processing. Using runtime packaging also reduces stack usage in the context which calls log message. Signed-off-by: Krzysztof Chruscinski <[email protected]>
2df7853
9f57b20
to
c7ed4f7
Compare
@SebastianBoe @dcpleung approvals have been withdrawn, rebased and applied @tejlmand comments. Please take another 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.
Looks good, only comment left is we should reduce the fatal error to a warning.
subsys/logging/CMakeLists.txt
Outdated
if (NOT CONFIG_LOG2_ALWAYS_RUNTIME) | ||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang") | ||
if(CMAKE_C_COMPILER_VERSION VERSION_LESS "3.8.0") | ||
message(FATAL_ERROR "Compiler version requires CONFIG_LOG2_ALWAYS_RUNTIME to be set") |
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 think we should downgrade this to WARNING
.
message(FATAL_ERROR "Compiler version requires CONFIG_LOG2_ALWAYS_RUNTIME to be set") | |
message(WARNING "Compiler version requires CONFIG_LOG2_ALWAYS_RUNTIME to be set") |
Reason, a fatal error will prevent users from running menuconfig and fix the problem, ref #9573
In principle FATAL_ERROR would be optimal here, but as users should be able to fix this using menuconfig, we have to go for less optimal solution.
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.
done
subsys/logging/CMakeLists.txt
Outdated
endif() | ||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU") | ||
if(CMAKE_C_COMPILER_VERSION VERSION_LESS "4.9.0") | ||
message(FATAL_ERROR "Compiler version requires CONFIG_LOG2_ALWAYS_RUNTIME to be set") |
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 think we should downgrade this to WARNING
.
message(FATAL_ERROR "Compiler version requires CONFIG_LOG2_ALWAYS_RUNTIME to be set") | |
message(WARNING "Compiler version requires CONFIG_LOG2_ALWAYS_RUNTIME to be set") |
Reason, a fatal error will prevent users from running menuconfig and fix the problem, ref #9573
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.
done
Logging v2 is utilizing complex preprocessing operations to prepare message at compile time. Multiple operations are peformed on log message arguments. However, it is expected that argument will be evaluated only once (e.g. it can be a call to a function with side effects). Adding additional layer which creates copies of user arguments on stack and passes them to further processing. Updated test for log_msg2 which is using internal macro which got renamed. Signed-off-by: Krzysztof Chruscinski <[email protected]>
Added test which checks that log argument is evaluated only once when log message is created. Signed-off-by: Krzysztof Chruscinski <[email protected]>
When immediate logging is used and optimization is off then bigger stack is needed for thread analyzer. Adjusting the value. Signed-off-by: Krzysztof Chruscinski <[email protected]>
Added test which estimates stack usage of few types of logging messages in various modes, with and without optimization. Test was used to determine usage for various architectures and is expected to be used to detect stack usage increase since it fails when stack usage in given configuration goes beyond the hardcoded limit. Signed-off-by: Krzysztof Chruscinski <[email protected]>
Add information about logging stack usage. Signed-off-by: Krzysztof Chruscinski <[email protected]>
c7ed4f7
to
abac3bc
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.
lgtm
This is another attempt to fix #42050. First attempt (#42165) was reverted (#42609) due to #42608. Test was failing because of increased stack usage after changes in logging. Increased stack usage has been seen in
CONFIG_NO_OPTIMIZATIONS=y
case.In this take, logging macro path has been changed so that runtime packaging (the one without preprocessor magic and multiple arguments evaluation) is used always when
CONFIG_NO_OPTIMIZATIONS=y
orCONFIG_LOG_MODE_IMMEDIATE=y
. In both cases static packaging is not needed since static packaging is used to get best performance and with those two options enabled it is not a case. Since preprocessor magic is used only when optimization is enabled, compiler handles it correctly, resolving all static values without bloating stack usage.Additionally, added a test (
tests/subsys/logging/log_stack
) for checking stack usage when logging is used. Test has been used to characterize stack usage for various architectures (it varies a lot) in 4 configurations:Test should detect any unexpected stack usage increases in logging area.
Fixes #42050.
Fixed #43016.