From 7831bfcce8f72ba3fc3f7312d9eeaf162dff8a81 Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Mon, 29 Nov 2021 08:49:57 +0100 Subject: [PATCH] lib: os: cbprintf: Add flags to CBPRINTF_MUST_RUNTIME_PACKAGE Add flags to macro which checks if string must be packaged using runtime approach. Added flag CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR. When flag is set then const char pointers are considered as pointers to fixed strings and do not require runtime packaging. Signed-off-by: Krzysztof Chruscinski --- include/logging/log_msg2.h | 4 +-- include/sys/cbprintf.h | 22 ++++++++++++-- include/sys/cbprintf_cxx.h | 40 ++++++++++++++----------- include/sys/cbprintf_internal.h | 21 ++++++------- tests/lib/cbprintf_package/src/test.inc | 2 +- tests/unit/cbprintf/main.c | 2 +- 6 files changed, 58 insertions(+), 33 deletions(-) diff --git a/include/logging/log_msg2.h b/include/logging/log_msg2.h index ba30bd7632b..8d9acce894e 100644 --- a/include/logging/log_msg2.h +++ b/include/logging/log_msg2.h @@ -358,7 +358,7 @@ do {\ _level, _data, _dlen, ...) \ do { \ Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \ - if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \ + if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, 0, __VA_ARGS__)) { \ LOG_MSG2_DBG("create runtime message\n");\ z_log_msg2_runtime_create(_domain_id, (void *)_source, \ _level, (uint8_t *)_data, _dlen,\ @@ -375,7 +375,7 @@ do { \ _level, _data, _dlen, ...) \ do { \ Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \ - if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \ + if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, 0, __VA_ARGS__)) { \ LOG_MSG2_DBG("create runtime message\n");\ z_log_msg2_runtime_create(_domain_id, (void *)_source, \ _level, (uint8_t *)_data, _dlen,\ diff --git a/include/sys/cbprintf.h b/include/sys/cbprintf.h index d9a68005cb2..0373975af8a 100644 --- a/include/sys/cbprintf.h +++ b/include/sys/cbprintf.h @@ -77,6 +77,19 @@ extern "C" { /**@} */ +/**@defgroup CBPRINTF_MUST_RUNTIME_PACKAGE_FLAGS Package flags. + * @{ + */ + +/** @brief Consider constant string pointers as pointing to fixed strings. + * + * When flag is set then const (w)char pointers arguments in the string does + * not trigger runtime packaging. + */ +#define CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR BIT(0) + +/**@} */ + /** @brief Signature for a cbprintf callback function. * * This function expects two parameters: @@ -103,17 +116,22 @@ typedef int (*cbprintf_cb)(/* int c, void *ctx */); * if there are no string arguments which might be copied into package body if * they are considered transient. * + * @note By default any char pointers are considered to be pointing at transient + * strings. This can be narrowed down to non const pointers by using + * @ref CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR. + * * @param skip number of read only string arguments in the parameter list. It * shall be non-zero if there are known read only string arguments present * in the string (e.g. function name prefix in the log message). * * @param ... String with arguments. + * @param flags option flags. See @ref CBPRINTF_MUST_RUNTIME_PACKAGE_FLAGS. * * @retval 1 if string must be packaged in run time. * @retval 0 string can be statically packaged. */ -#define CBPRINTF_MUST_RUNTIME_PACKAGE(skip, ... /* fmt, ... */) \ - Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, __VA_ARGS__) +#define CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ... /* fmt, ... */) \ + Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, __VA_ARGS__) /** @brief Statically package string. * diff --git a/include/sys/cbprintf_cxx.h b/include/sys/cbprintf_cxx.h index 0f79f879285..692618a678f 100644 --- a/include/sys/cbprintf_cxx.h +++ b/include/sys/cbprintf_cxx.h @@ -9,51 +9,57 @@ #ifdef __cplusplus /* C++ version for detecting a pointer to a string. */ -static inline int z_cbprintf_cxx_is_pchar(char *) +static inline int z_cbprintf_cxx_is_pchar(char *, bool const_as_fixed) { return 1; } -static inline int z_cbprintf_cxx_is_pchar(const char *) +static inline int z_cbprintf_cxx_is_pchar(const char *, bool const_as_fixed) { + return const_as_fixed ? 0 : 1; +} + +static inline int z_cbprintf_cxx_is_pchar(volatile char *, bool const_as_fixed) +{ + ARG_UNUSED(const_as_fixed); return 1; } -static inline int z_cbprintf_cxx_is_pchar(volatile char *) +static inline int z_cbprintf_cxx_is_pchar(const volatile char *, bool const_as_fixed) { + ARG_UNUSED(const_as_fixed); return 1; } -static inline int z_cbprintf_cxx_is_pchar(const volatile char *) +static inline int z_cbprintf_cxx_is_pchar(wchar_t *, bool const_as_fixed) { + ARG_UNUSED(const_as_fixed); return 1; } -static inline int z_cbprintf_cxx_is_pchar(wchar_t *) +static inline int z_cbprintf_cxx_is_pchar(const wchar_t *, bool const_as_fixed) { + return const_as_fixed ? 0 : 1; +} + +static inline int z_cbprintf_cxx_is_pchar(volatile wchar_t *, bool const_as_fixed) +{ + ARG_UNUSED(const_as_fixed); return 1; } -static inline int z_cbprintf_cxx_is_pchar(const wchar_t *) -{ - return 1; -} - -static inline int z_cbprintf_cxx_is_pchar(volatile wchar_t *) -{ - return 1; -} - -static inline int z_cbprintf_cxx_is_pchar(const volatile wchar_t *) +static inline int z_cbprintf_cxx_is_pchar(const volatile wchar_t *, bool const_as_fixed) { + ARG_UNUSED(const_as_fixed); return 1; } template < typename T > -static inline int z_cbprintf_cxx_is_pchar(T arg) +static inline int z_cbprintf_cxx_is_pchar(T arg, bool const_as_fixed) { _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") + ARG_UNUSED(const_as_fixed); return 0; _Pragma("GCC diagnostic pop") } diff --git a/include/sys/cbprintf_internal.h b/include/sys/cbprintf_internal.h index 6b09023b9d4..bad41f7ba1c 100644 --- a/include/sys/cbprintf_internal.h +++ b/include/sys/cbprintf_internal.h @@ -85,16 +85,17 @@ extern "C" { * @return 1 if char * or wchar_t *, 0 otherwise. */ #ifdef __cplusplus -#define Z_CBPRINTF_IS_PCHAR(x) z_cbprintf_cxx_is_pchar(x) +#define Z_CBPRINTF_IS_PCHAR(x, flags) \ + z_cbprintf_cxx_is_pchar(x, flags & CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR) #else -#define Z_CBPRINTF_IS_PCHAR(x) \ +#define Z_CBPRINTF_IS_PCHAR(x, flags) \ _Generic((x) + 0, \ char * : 1, \ - const char * : 1, \ + const char * : (flags & CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR) ? 0 : 1, \ volatile char * : 1, \ const volatile char * : 1, \ wchar_t * : 1, \ - const wchar_t * : 1, \ + const wchar_t * : (flags & CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR) ? 0 : 1, \ volatile wchar_t * : 1, \ const volatile wchar_t * : 1, \ default : \ @@ -109,8 +110,8 @@ extern "C" { * * @return number of arguments which are char * or wchar_t *. */ -#define Z_CBPRINTF_HAS_PCHAR_ARGS(fmt, ...) \ - (FOR_EACH(Z_CBPRINTF_IS_PCHAR, (+), __VA_ARGS__)) +#define Z_CBPRINTF_HAS_PCHAR_ARGS(flags, fmt, ...) \ + (FOR_EACH_FIXED_ARG(Z_CBPRINTF_IS_PCHAR, (+), flags, __VA_ARGS__)) /** * @brief Check if formatted string must be packaged in runtime. @@ -124,17 +125,17 @@ extern "C" { * @retval 0 if string can be statically packaged. */ #if Z_C_GENERIC -#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, ...) ({\ +#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ...) ({\ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \ int _rv = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \ (0), \ - (((Z_CBPRINTF_HAS_PCHAR_ARGS(__VA_ARGS__) - skip) > 0))); \ + (((Z_CBPRINTF_HAS_PCHAR_ARGS(flags, __VA_ARGS__) - skip) > 0))); \ _Pragma("GCC diagnostic pop")\ _rv; \ }) #else -#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, ...) 1 +#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ...) 1 #endif /** @brief Get storage size for given argument. @@ -271,7 +272,7 @@ do { \ _align_offset += sizeof(int); \ } \ uint32_t _arg_size = Z_CBPRINTF_ARG_SIZE(_arg); \ - if (Z_CBPRINTF_IS_PCHAR(_arg)) { \ + if (Z_CBPRINTF_IS_PCHAR(_arg, 0)) { \ _s_buf[_s_idx++] = _idx / sizeof(int); \ } \ if (_buf && _idx < (int)_max) { \ diff --git a/tests/lib/cbprintf_package/src/test.inc b/tests/lib/cbprintf_package/src/test.inc index 90b40c0346c..dc6fa12ec69 100644 --- a/tests/lib/cbprintf_package/src/test.inc +++ b/tests/lib/cbprintf_package/src/test.inc @@ -57,7 +57,7 @@ static void unpack(const char *desc, struct out_buffer *buf, } #define TEST_PACKAGING(fmt, ...) do { \ - int must_runtime = CBPRINTF_MUST_RUNTIME_PACKAGE(0, fmt, __VA_ARGS__); \ + int must_runtime = CBPRINTF_MUST_RUNTIME_PACKAGE(0, 0, fmt, __VA_ARGS__); \ zassert_equal(must_runtime, !Z_C_GENERIC, NULL); \ snprintfcb(compare_buf, sizeof(compare_buf), fmt, __VA_ARGS__); \ printk("-----------------------------------------\n"); \ diff --git a/tests/unit/cbprintf/main.c b/tests/unit/cbprintf/main.c index b4c40d7f820..d1df31019d4 100644 --- a/tests/unit/cbprintf/main.c +++ b/tests/unit/cbprintf/main.c @@ -294,7 +294,7 @@ static int rawprf(const char *format, ...) #define TEST_PRF2(rc, _fmt, ...) do { \ char _buf[512]; \ char *sp_buf = NULL; /* static package buffer */\ - if (USE_PACKAGED && !CBPRINTF_MUST_RUNTIME_PACKAGE(0, _fmt, __VA_ARGS__)) { \ + if (USE_PACKAGED && !CBPRINTF_MUST_RUNTIME_PACKAGE(0, 0, _fmt, __VA_ARGS__)) { \ int rv = 0; \ size_t _len; \ struct out_buffer package_buf = { \