LCOV - code coverage report
Current view: top level - zephyr/logging - log_msg.h Coverage Total Hit
Test: new.info Lines: 28.3 % 46 13
Test Date: 2025-09-05 16:43:28

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2021 Nordic Semiconductor ASA
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : #ifndef ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_
       7              : #define ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_
       8              : 
       9              : #include <zephyr/logging/log_instance.h>
      10              : #include <zephyr/sys/mpsc_packet.h>
      11              : #include <zephyr/sys/cbprintf.h>
      12              : #include <zephyr/sys/atomic.h>
      13              : #include <zephyr/sys/iterable_sections.h>
      14              : #include <zephyr/sys/util.h>
      15              : #include <string.h>
      16              : #include <zephyr/toolchain.h>
      17              : 
      18              : #ifdef __GNUC__
      19              : #ifndef alloca
      20              : #define alloca __builtin_alloca
      21              : #endif
      22              : #else
      23              : #include <alloca.h>
      24              : #endif
      25              : 
      26              : #ifdef __cplusplus
      27              : extern "C" {
      28              : #endif
      29              : 
      30            0 : #define LOG_MSG_DEBUG 0
      31            0 : #define LOG_MSG_DBG(...) IF_ENABLED(LOG_MSG_DEBUG, (printk(__VA_ARGS__)))
      32              : 
      33              : #ifdef CONFIG_LOG_TIMESTAMP_64BIT
      34              : typedef uint64_t log_timestamp_t;
      35              : #else
      36            0 : typedef uint32_t log_timestamp_t;
      37              : #endif
      38              : 
      39              : /**
      40              :  * @brief Log message API
      41              :  * @defgroup log_msg Log message API
      42              :  * @ingroup logger
      43              :  * @{
      44              :  */
      45              : 
      46              : #define Z_LOG_MSG_LOG 0
      47              : 
      48              : #define Z_LOG_MSG_PACKAGE_BITS 11
      49              : 
      50              : #define Z_LOG_MSG_MAX_PACKAGE BIT_MASK(Z_LOG_MSG_PACKAGE_BITS)
      51              : 
      52            0 : #define LOG_MSG_GENERIC_HDR \
      53              :         MPSC_PBUF_HDR;\
      54              :         uint32_t type:1
      55              : 
      56            0 : struct log_msg_desc {
      57            0 :         LOG_MSG_GENERIC_HDR;
      58            0 :         uint32_t domain:3;
      59            0 :         uint32_t level:3;
      60            0 :         uint32_t package_len:Z_LOG_MSG_PACKAGE_BITS;
      61            0 :         uint32_t data_len:12;
      62              : };
      63              : 
      64            0 : union log_msg_source {
      65            0 :         const struct log_source_const_data *fixed;
      66            0 :         struct log_source_dynamic_data *dynamic;
      67            0 :         void *raw;
      68              : };
      69              : 
      70            0 : struct log_msg_hdr {
      71            0 :         struct log_msg_desc desc;
      72              : /* Attempting to keep best alignment. When address is 64 bit and timestamp 32
      73              :  * swap the order to have 16 byte header instead of 24 byte.
      74              :  */
      75              : #if (INTPTR_MAX > INT32_MAX) && !defined(CONFIG_LOG_TIMESTAMP_64BIT)
      76              :         log_timestamp_t timestamp;
      77              :         const void *source;
      78              : #else
      79            0 :         const void *source;
      80            0 :         log_timestamp_t timestamp;
      81              : #endif
      82              : #if defined(CONFIG_LOG_THREAD_ID_PREFIX)
      83              :         void *tid;
      84              : #endif
      85              : };
      86              : /* Messages are aligned to alignment required by cbprintf package. */
      87              : #define Z_LOG_MSG_ALIGNMENT CBPRINTF_PACKAGE_ALIGNMENT
      88              : 
      89              : #define Z_LOG_MSG_PADDING \
      90              :         ((sizeof(struct log_msg_hdr) % Z_LOG_MSG_ALIGNMENT) > 0 ? \
      91              :         (Z_LOG_MSG_ALIGNMENT - (sizeof(struct log_msg_hdr) % Z_LOG_MSG_ALIGNMENT)) : \
      92              :                 0)
      93              : 
      94            0 : struct log_msg {
      95            0 :         struct log_msg_hdr hdr;
      96              :         /* Adding padding to ensure that cbprintf package that follows is
      97              :          * properly aligned.
      98              :          */
      99            0 :         uint8_t padding[Z_LOG_MSG_PADDING];
     100            0 :         uint8_t data[];
     101              : };
     102              : 
     103              : /**
     104              :  * @cond INTERNAL_HIDDEN
     105              :  */
     106              : BUILD_ASSERT(sizeof(struct log_msg) % Z_LOG_MSG_ALIGNMENT == 0,
     107              :              "Log msg size must aligned");
     108              : /**
     109              :  * @endcond
     110              :  */
     111              : 
     112              : 
     113            0 : struct log_msg_generic_hdr {
     114            0 :         LOG_MSG_GENERIC_HDR;
     115              : };
     116              : 
     117            0 : union log_msg_generic {
     118            0 :         union mpsc_pbuf_generic buf;
     119            0 :         struct log_msg_generic_hdr generic;
     120            0 :         struct log_msg log;
     121              : };
     122              : 
     123              : /** @brief Method used for creating a log message.
     124              :  *
     125              :  * It is used for testing purposes to validate that expected mode was used.
     126              :  */
     127              : enum z_log_msg_mode {
     128              :         /* Runtime mode is least efficient but supports all cases thus it is
     129              :          * treated as a fallback method when others cannot be used.
     130              :          */
     131              :         Z_LOG_MSG_MODE_RUNTIME,
     132              :         /* Mode creates statically a string package on stack and calls a
     133              :          * function for creating a message. It takes code size than
     134              :          * Z_LOG_MSG_MODE_ZERO_COPY but is a bit slower.
     135              :          */
     136              :         Z_LOG_MSG_MODE_FROM_STACK,
     137              : 
     138              :         /* Mode calculates size of the message and allocates it and writes
     139              :          * directly to the message space. It is the fastest method but requires
     140              :          * more code size.
     141              :          */
     142              :         Z_LOG_MSG_MODE_ZERO_COPY,
     143              : 
     144              :         /* Mode optimized for simple messages with 0 to 2 32 bit word arguments.*/
     145              :         Z_LOG_MSG_MODE_SIMPLE,
     146              : };
     147              : 
     148              : #define Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, _plen, _dlen) \
     149              : { \
     150              :         .valid = 0, \
     151              :         .busy = 0, \
     152              :         .type = Z_LOG_MSG_LOG, \
     153              :         .domain = (_domain_id), \
     154              :         .level = (_level), \
     155              :         .package_len = (_plen), \
     156              :         .data_len = (_dlen), \
     157              : }
     158              : 
     159              : #define Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) \
     160              :         (CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt) | \
     161              :         (IS_ENABLED(CONFIG_LOG_MSG_APPEND_RO_STRING_LOC) ? \
     162              :          CBPRINTF_PACKAGE_ADD_STRING_IDXS : 0))
     163              : 
     164              : #ifdef CONFIG_LOG_USE_VLA
     165              : #define Z_LOG_MSG_ON_STACK_ALLOC(ptr, len) \
     166              :         long long _ll_buf[DIV_ROUND_UP(len, sizeof(long long))]; \
     167              :         long double _ld_buf[DIV_ROUND_UP(len, sizeof(long double))]; \
     168              :         (ptr) = (sizeof(long double) == Z_LOG_MSG_ALIGNMENT) ? \
     169              :                         (struct log_msg *)_ld_buf : (struct log_msg *)_ll_buf; \
     170              :         if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
     171              :                 /* During test fill with 0's to simplify message comparison */ \
     172              :                 memset((ptr), 0, (len)); \
     173              :         }
     174              : #else /* Z_LOG_MSG_USE_VLA */
     175              : /* When VLA cannot be used we need to trick compiler a bit and create multiple
     176              :  * fixed size arrays and take the smallest one that will fit the message.
     177              :  * Compiler will remove unused arrays and stack usage will be kept similar
     178              :  * to vla case, rounded to the size of the used buffer.
     179              :  */
     180              : #define Z_LOG_MSG_ON_STACK_ALLOC(ptr, len) \
     181              :         long long _ll_buf32[32 / sizeof(long long)]; \
     182              :         long long _ll_buf48[48 / sizeof(long long)]; \
     183              :         long long _ll_buf64[64 / sizeof(long long)]; \
     184              :         long long _ll_buf128[128 / sizeof(long long)]; \
     185              :         long long _ll_buf256[256 / sizeof(long long)]; \
     186              :         long double _ld_buf32[32 / sizeof(long double)]; \
     187              :         long double _ld_buf48[48 / sizeof(long double)]; \
     188              :         long double _ld_buf64[64 / sizeof(long double)]; \
     189              :         long double _ld_buf128[128 / sizeof(long double)]; \
     190              :         long double _ld_buf256[256 / sizeof(long double)]; \
     191              :         if (sizeof(long double) == Z_LOG_MSG_ALIGNMENT) { \
     192              :                 ptr = (len > 128) ? (struct log_msg *)_ld_buf256 : \
     193              :                         ((len > 64) ? (struct log_msg *)_ld_buf128 : \
     194              :                         ((len > 48) ? (struct log_msg *)_ld_buf64 : \
     195              :                         ((len > 32) ? (struct log_msg *)_ld_buf48 : \
     196              :                                       (struct log_msg *)_ld_buf32)));\
     197              :         } else { \
     198              :                 ptr = (len > 128) ? (struct log_msg *)_ll_buf256 : \
     199              :                         ((len > 64) ? (struct log_msg *)_ll_buf128 : \
     200              :                         ((len > 48) ? (struct log_msg *)_ll_buf64 : \
     201              :                         ((len > 32) ? (struct log_msg *)_ll_buf48 : \
     202              :                                       (struct log_msg *)_ll_buf32)));\
     203              :         } \
     204              :         if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
     205              :                 /* During test fill with 0's to simplify message comparison */ \
     206              :                 memset((ptr), 0, (len)); \
     207              :         }
     208              : #endif /* Z_LOG_MSG_USE_VLA */
     209              : 
     210              : #define Z_LOG_MSG_ALIGN_OFFSET \
     211              :         offsetof(struct log_msg, data)
     212              : 
     213              : #define Z_LOG_MSG_LEN(pkg_len, data_len) \
     214              :         (offsetof(struct log_msg, data) + (pkg_len) + (data_len))
     215              : 
     216              : #define Z_LOG_MSG_ALIGNED_WLEN(pkg_len, data_len) \
     217              :         DIV_ROUND_UP(ROUND_UP(Z_LOG_MSG_LEN(pkg_len, data_len), \
     218              :                                   Z_LOG_MSG_ALIGNMENT), \
     219              :                          sizeof(uint32_t))
     220              : 
     221              : /*
     222              :  * With Zephyr SDK 0.14.2, aarch64-zephyr-elf-gcc (10.3.0) fails to ensure $sp
     223              :  * is below the active memory during message construction. As a result,
     224              :  * interrupts happening in the middle of that process can end up smashing active
     225              :  * data and causing a logging fault. Work around this by inserting a compiler
     226              :  * barrier after the allocation and before any use to make sure GCC moves the
     227              :  * stack pointer soon enough
     228              :  */
     229              : 
     230              : #define Z_LOG_ARM64_VLA_PROTECT() compiler_barrier()
     231              : 
     232              : #define _LOG_MSG_SIMPLE_XXXX0 1
     233              : #define _LOG_MSG_SIMPLE_XXXX1 1
     234              : #define _LOG_MSG_SIMPLE_XXXX2 1
     235              : 
     236              : /* Determine if amount of arguments (less than 3) qualifies to  simple message. */
     237            0 : #define LOG_MSG_SIMPLE_ARG_CNT_CHECK(...) \
     238              :         COND_CODE_1(UTIL_CAT(_LOG_MSG_SIMPLE_XXXX, NUM_VA_ARGS_LESS_1(__VA_ARGS__)), (1), (0))
     239              : 
     240              : /* Set of marcos used to determine if arguments type allows simplified message creation mode. */
     241            0 : #define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_0(fmt) 1
     242            0 : #define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_1(fmt, arg) Z_CBPRINTF_IS_WORD_NUM(arg)
     243            0 : #define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_2(fmt, arg0, arg1) \
     244              :         Z_CBPRINTF_IS_WORD_NUM(arg0) && Z_CBPRINTF_IS_WORD_NUM(arg1)
     245              : 
     246              : /** brief Determine if string arguments types allow to use simplified message creation mode.
     247              :  *
     248              :  * @param ... String with arguments.
     249              :  */
     250            1 : #define LOG_MSG_SIMPLE_ARG_TYPE_CHECK(...) \
     251              :         UTIL_CAT(LOG_MSG_SIMPLE_ARG_TYPE_CHECK_, NUM_VA_ARGS_LESS_1(__VA_ARGS__))(__VA_ARGS__)
     252              : 
     253              : /** @brief Check if message can be handled using simplified method.
     254              :  *
     255              :  * Following conditions must be met:
     256              :  * - 32 bit platform
     257              :  * - Number of arguments from 0 to 2
     258              :  * - Type of an argument must be a numeric value that fits in 32 bit word.
     259              :  *
     260              :  * @param ... String with arguments.
     261              :  *
     262              :  * @retval 1 if message qualifies.
     263              :  * @retval 0 if message does not qualify.
     264              :  */
     265            1 : #define LOG_MSG_SIMPLE_CHECK(...) \
     266              :         COND_CODE_1(CONFIG_64BIT, (0), (\
     267              :                 COND_CODE_1(LOG_MSG_SIMPLE_ARG_CNT_CHECK(__VA_ARGS__), ( \
     268              :                                 LOG_MSG_SIMPLE_ARG_TYPE_CHECK(__VA_ARGS__)), (0))))
     269              : 
     270              : /* Helper macro for handing log with one argument. Macro casts the first argument to uint32_t. */
     271              : #define Z_LOG_MSG_SIMPLE_CREATE_1(_source, _level, ...) \
     272              :         z_log_msg_simple_create_1(_source, _level, GET_ARG_N(1, __VA_ARGS__), \
     273              :                         (uint32_t)(uintptr_t)GET_ARG_N(2, __VA_ARGS__))
     274              : 
     275              : /* Helper macro for handing log with two arguments. Macro casts arguments to uint32_t.
     276              :  */
     277              : #define Z_LOG_MSG_SIMPLE_CREATE_2(_source, _level, ...) \
     278              :         z_log_msg_simple_create_2(_source, _level, GET_ARG_N(1, __VA_ARGS__), \
     279              :                         (uint32_t)(uintptr_t)GET_ARG_N(2, __VA_ARGS__), \
     280              :                         (uint32_t)(uintptr_t)GET_ARG_N(3, __VA_ARGS__))
     281              : 
     282              : /* Call specific function based on the number of arguments.
     283              :  * Since up 2 to arguments are supported COND_CODE_0 and COND_CODE_1 can be used to
     284              :  * handle all cases (0, 1 and 2 arguments). When tracing is enable then for each
     285              :  * function a macro is create. The difference between function and macro is that
     286              :  * macro is applied to any input arguments so we need to make sure that it is
     287              :  * always called with proper number of arguments. For that it is wrapped around
     288              :  * into another macro and dummy arguments to cover for cases when there is less
     289              :  * arguments in a log call.
     290              :  */
     291              : #define Z_LOG_MSG_SIMPLE_FUNC2(arg_cnt, _source, _level, ...) \
     292              :         COND_CODE_0(arg_cnt, \
     293              :                         (z_log_msg_simple_create_0(_source, _level, GET_ARG_N(1, __VA_ARGS__))), \
     294              :                         (COND_CODE_1(arg_cnt, ( \
     295              :                             Z_LOG_MSG_SIMPLE_CREATE_1(_source, _level, __VA_ARGS__, dummy) \
     296              :                             ), ( \
     297              :                             Z_LOG_MSG_SIMPLE_CREATE_2(_source, _level, __VA_ARGS__, dummy, dummy) \
     298              :                             ) \
     299              :                         )))
     300              : 
     301              : /** @brief Call specific function to create a log message.
     302              :  *
     303              :  * Macro picks matching function (based on number of arguments) and calls it.
     304              :  * String arguments are casted to uint32_t.
     305              :  *
     306              :  * @param _source       Source.
     307              :  * @param _level        Severity level.
     308              :  * @param ...           String with arguments.
     309              :  */
     310            1 : #define LOG_MSG_SIMPLE_FUNC(_source, _level, ...) \
     311              :         Z_LOG_MSG_SIMPLE_FUNC2(NUM_VA_ARGS_LESS_1(__VA_ARGS__), _source, _level, __VA_ARGS__)
     312              : 
     313              : /** @brief Create log message using simplified method.
     314              :  *
     315              :  * Macro is gated by the argument count check to run @ref LOG_MSG_SIMPLE_FUNC only
     316              :  * on entries with 2 or less arguments.
     317              :  *
     318              :  * @param _domain_id    Domain ID.
     319              :  * @param _source       Pointer to the source structure.
     320              :  * @param _level        Severity level.
     321              :  * @param ...           String with arguments.
     322              :  */
     323              : #define Z_LOG_MSG_SIMPLE_ARGS_CREATE(_domain_id, _source, _level, ...) \
     324              :         IF_ENABLED(LOG_MSG_SIMPLE_ARG_CNT_CHECK(__VA_ARGS__), (\
     325              :                 LOG_MSG_SIMPLE_FUNC(_source, _level, __VA_ARGS__); \
     326              :         ))
     327              : 
     328              : #define Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, _dlen, ...) \
     329              : do { \
     330              :         int _plen; \
     331              :         uint32_t _options = Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) | \
     332              :                           CBPRINTF_PACKAGE_ADD_RW_STR_POS; \
     333              :         if (GET_ARG_N(1, __VA_ARGS__) == NULL) { \
     334              :                 _plen = 0; \
     335              :         } else { \
     336              :                 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG_ALIGN_OFFSET, _options, \
     337              :                                         __VA_ARGS__); \
     338              :         } \
     339              :         TOOLCHAIN_DISABLE_WARNING(TOOLCHAIN_WARNING_SHADOW) \
     340              :         struct log_msg *_msg; \
     341              :         TOOLCHAIN_ENABLE_WARNING(TOOLCHAIN_WARNING_SHADOW) \
     342              :         Z_LOG_MSG_ON_STACK_ALLOC(_msg, Z_LOG_MSG_LEN(_plen, 0)); \
     343              :         Z_LOG_ARM64_VLA_PROTECT(); \
     344              :         if (_plen != 0) { \
     345              :                 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, \
     346              :                                         _plen, Z_LOG_MSG_ALIGN_OFFSET, _options, \
     347              :                                         __VA_ARGS__);\
     348              :         } \
     349              :         struct log_msg_desc _desc = \
     350              :                 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
     351              :                                            (uint32_t)_plen, _dlen); \
     352              :         LOG_MSG_DBG("creating message on stack: package len: %d, data len: %d\n", \
     353              :                         _plen, (int)(_dlen)); \
     354              :         z_log_msg_static_create((void *)(_source), _desc, _msg->data, (_data)); \
     355              : } while (false)
     356              : 
     357              : #ifdef CONFIG_LOG_SPEED
     358              : #define Z_LOG_MSG_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, _level, ...) do { \
     359              :         int _plen; \
     360              :         CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG_ALIGN_OFFSET, \
     361              :                                 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
     362              :                                 __VA_ARGS__); \
     363              :         size_t _msg_wlen = Z_LOG_MSG_ALIGNED_WLEN(_plen, 0); \
     364              :         struct log_msg *_msg = z_log_msg_alloc(_msg_wlen); \
     365              :         struct log_msg_desc _desc = \
     366              :                 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, (uint32_t)_plen, 0); \
     367              :         LOG_MSG_DBG("creating message zero copy: package len: %d, msg: %p\n", \
     368              :                         _plen, _msg); \
     369              :         if (_msg) { \
     370              :                 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
     371              :                                         Z_LOG_MSG_ALIGN_OFFSET, \
     372              :                                         Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
     373              :                                         __VA_ARGS__); \
     374              :         } \
     375              :         z_log_msg_finalize(_msg, (void *)_source, _desc, NULL); \
     376              : } while (false)
     377              : #else
     378              : /* Alternative empty macro created to speed up compilation when LOG_SPEED is
     379              :  * disabled (default).
     380              :  */
     381              : #define Z_LOG_MSG_SIMPLE_CREATE(...)
     382              : #endif
     383              : 
     384              : /* Macro handles case when local variable with log message string is created. It
     385              :  * replaces original string literal with that variable.
     386              :  */
     387              : #define Z_LOG_FMT_ARGS_2(_name, ...) \
     388              :         COND_CODE_1(CONFIG_LOG_FMT_SECTION, \
     389              :                 (COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
     390              :                    (_name), (_name, GET_ARGS_LESS_N(1, __VA_ARGS__)))), \
     391              :                 (__VA_ARGS__))
     392              : 
     393              : /** @brief Wrapper for log message string with arguments.
     394              :  *
     395              :  * Wrapper is replacing first argument with a variable from a dedicated memory
     396              :  * section if option is enabled. Macro handles the case when there is no
     397              :  * log message provided.
     398              :  *
     399              :  * @param _name Name of the variable with log message string. It is optionally used.
     400              :  * @param ... Optional log message with arguments (may be empty).
     401              :  */
     402              : #define Z_LOG_FMT_ARGS(_name, ...) \
     403              :         COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
     404              :                 (NULL), \
     405              :                 (Z_LOG_FMT_ARGS_2(_name, ##__VA_ARGS__)))
     406              : 
     407              : #if defined(CONFIG_LOG_USE_TAGGED_ARGUMENTS)
     408              : 
     409              : #define Z_LOG_FMT_TAGGED_ARGS_2(_name, ...) \
     410              :         COND_CODE_1(CONFIG_LOG_FMT_SECTION, \
     411              :                     (_name, Z_CBPRINTF_TAGGED_ARGS(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
     412              :                                                    GET_ARGS_LESS_N(1, __VA_ARGS__))), \
     413              :                     (GET_ARG_N(1, __VA_ARGS__), \
     414              :                      Z_CBPRINTF_TAGGED_ARGS(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
     415              :                                             GET_ARGS_LESS_N(1, __VA_ARGS__))))
     416              : 
     417              : /** @brief Wrapper for log message string with tagged arguments.
     418              :  *
     419              :  * Wrapper is replacing first argument with a variable from a dedicated memory
     420              :  * section if option is enabled. Macro handles the case when there is no
     421              :  * log message provided. Each subsequent arguments are tagged by preceding
     422              :  * each argument with its type value.
     423              :  *
     424              :  * @param _name Name of the variable with log message string. It is optionally used.
     425              :  * @param ... Optional log message with arguments (may be empty).
     426              :  */
     427              : #define Z_LOG_FMT_TAGGED_ARGS(_name, ...) \
     428              :         COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
     429              :                 (Z_CBPRINTF_TAGGED_ARGS(0)), \
     430              :                 (Z_LOG_FMT_TAGGED_ARGS_2(_name, ##__VA_ARGS__)))
     431              : 
     432              : #define Z_LOG_FMT_RUNTIME_ARGS(...) \
     433              :         Z_LOG_FMT_TAGGED_ARGS(__VA_ARGS__)
     434              : 
     435              : #else
     436              : 
     437              : #define Z_LOG_FMT_RUNTIME_ARGS(...) \
     438              :         Z_LOG_FMT_ARGS(__VA_ARGS__)
     439              : 
     440              : #endif /* CONFIG_LOG_USE_TAGGED_ARGUMENTS */
     441              : 
     442              : /* Macro handles case when there is no string provided, in that case variable
     443              :  * is not created.
     444              :  */
     445              : #define Z_LOG_MSG_STR_VAR_IN_SECTION(_name, ...) \
     446              :         COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
     447              :                     (/* No args provided, no variable */), \
     448              :                     (static const char _name[] \
     449              :                      __in_section(_log_strings, static, _CONCAT(_name, _)) __used __noasan = \
     450              :                         GET_ARG_N(1, __VA_ARGS__);))
     451              : 
     452              : /** @brief Create variable in the dedicated memory section (if enabled).
     453              :  *
     454              :  * Variable is initialized with a format string from the log message.
     455              :  *
     456              :  * @param _name Variable name.
     457              :  * @param ... Optional log message with arguments (may be empty).
     458              :  */
     459              : #define Z_LOG_MSG_STR_VAR(_name, ...) \
     460              :         IF_ENABLED(CONFIG_LOG_FMT_SECTION, \
     461              :                    (Z_LOG_MSG_STR_VAR_IN_SECTION(_name, ##__VA_ARGS__)))
     462              : 
     463              : /** @brief Create log message and write it into the logger buffer.
     464              :  *
     465              :  * Macro handles creation of log message which includes storing log message
     466              :  * description, timestamp, arguments, copying string arguments into message and
     467              :  * copying user data into the message space. There are 3 modes of message
     468              :  * creation:
     469              :  * - at compile time message size is determined, message is allocated and
     470              :  *   content is written directly to the message. It is the fastest but cannot
     471              :  *   be used in user mode. Message size cannot be determined at compile time if
     472              :  *   it contains data or string arguments which are string pointers.
     473              :  * - at compile time message size is determined, string package is created on
     474              :  *   stack, message is created in function call. String package can only be
     475              :  *   created on stack if it does not contain unexpected pointers to strings.
     476              :  * - string package is created at runtime. This mode has no limitations but
     477              :  *   it is significantly slower.
     478              :  *
     479              :  * @param _try_0cpy If positive then, if possible, message content is written
     480              :  * directly to message. If 0 then, if possible, string package is created on
     481              :  * the stack and message is created in the function call.
     482              :  *
     483              :  * @param _mode Used for testing. It is set according to message creation mode
     484              :  *              used.
     485              :  *
     486              :  * @param _cstr_cnt Number of constant strings present in the string. It is
     487              :  * used to help detect messages which must be runtime processed, compared to
     488              :  * message which can be prebuilt at compile time.
     489              :  *
     490              :  * @param _domain_id Domain ID.
     491              :  *
     492              :  * @param _source Pointer to the constant descriptor of the log message source.
     493              :  *
     494              :  * @param _level Log message level.
     495              :  *
     496              :  * @param _data Pointer to the data. Can be null.
     497              :  *
     498              :  * @param _dlen Number of data bytes. 0 if data is not provided.
     499              :  *
     500              :  * @param ...  Optional string with arguments (fmt, ...). It may be empty.
     501              :  */
     502              : #if defined(CONFIG_LOG_ALWAYS_RUNTIME) || !defined(CONFIG_LOG)
     503              : #define Z_LOG_MSG_CREATE2(_try_0cpy, _mode,  _cstr_cnt, _domain_id, _source,\
     504              :                           _level, _data, _dlen, ...) \
     505              : do {\
     506              :         Z_LOG_MSG_STR_VAR(_fmt, ##__VA_ARGS__) \
     507              :         z_log_msg_runtime_create((_domain_id), (void *)(_source), \
     508              :                                   (_level), (uint8_t *)(_data), (_dlen),\
     509              :                                   Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) | \
     510              :                                   (IS_ENABLED(CONFIG_LOG_USE_TAGGED_ARGUMENTS) ? \
     511              :                                    CBPRINTF_PACKAGE_ARGS_ARE_TAGGED : 0), \
     512              :                                   Z_LOG_FMT_RUNTIME_ARGS(_fmt, ##__VA_ARGS__));\
     513              :         (_mode) = Z_LOG_MSG_MODE_RUNTIME; \
     514              : } while (false)
     515              : #else /* CONFIG_LOG_ALWAYS_RUNTIME || !CONFIG_LOG */
     516              : #define Z_LOG_MSG_CREATE3(_try_0cpy, _mode,  _cstr_cnt, _domain_id, _source,\
     517              :                           _level, _data, _dlen, ...) \
     518              : do { \
     519              :         Z_LOG_MSG_STR_VAR(_fmt, ##__VA_ARGS__); \
     520              :         bool has_rw_str = CBPRINTF_MUST_RUNTIME_PACKAGE( \
     521              :                                         Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
     522              :                                         __VA_ARGS__); \
     523              :         if (IS_ENABLED(CONFIG_LOG_SPEED) && (_try_0cpy) && ((_dlen) == 0) && !has_rw_str) {\
     524              :                 LOG_MSG_DBG("create zero-copy message\n");\
     525              :                 Z_LOG_MSG_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, \
     526              :                                         _level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
     527              :                 (_mode) = Z_LOG_MSG_MODE_ZERO_COPY; \
     528              :         } else { \
     529              :                 IF_ENABLED(UTIL_AND(IS_ENABLED(CONFIG_LOG_SIMPLE_MSG_OPTIMIZE), \
     530              :                                     UTIL_AND(UTIL_NOT(_domain_id), UTIL_NOT(_cstr_cnt))), \
     531              :                         ( \
     532              :                         bool can_simple = LOG_MSG_SIMPLE_CHECK(__VA_ARGS__); \
     533              :                         if (can_simple && ((_dlen) == 0) && !k_is_user_context()) { \
     534              :                                 LOG_MSG_DBG("create fast message\n");\
     535              :                                 Z_LOG_MSG_SIMPLE_ARGS_CREATE(_domain_id, _source, _level, \
     536              :                                                      Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
     537              :                                 _mode = Z_LOG_MSG_MODE_SIMPLE; \
     538              :                                 break; \
     539              :                         } \
     540              :                         ) \
     541              :                 ) \
     542              :                 LOG_MSG_DBG("create on stack message\n");\
     543              :                 Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, \
     544              :                                         _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
     545              :                 (_mode) = Z_LOG_MSG_MODE_FROM_STACK; \
     546              :         } \
     547              :         (void)(_mode); \
     548              : } while (false)
     549              : 
     550              : #if defined(__cplusplus)
     551              : #define Z_AUTO_TYPE auto
     552              : #else
     553              : #define Z_AUTO_TYPE __auto_type
     554              : #endif
     555              : 
     556              : /* Macro for getting name of a local variable with the exception of the first argument
     557              :  * which is a formatted string in log message.
     558              :  */
     559              : #define Z_LOG_LOCAL_ARG_NAME(idx, arg) COND_CODE_0(idx, (arg), (_v##idx))
     560              : 
     561              : /* Create local variable from input variable (expect for the first (fmt) argument). */
     562              : #define Z_LOG_LOCAL_ARG_CREATE(idx, arg) \
     563              :         COND_CODE_0(idx, (), (Z_AUTO_TYPE Z_LOG_LOCAL_ARG_NAME(idx, arg) = Z_ARGIFY(arg)))
     564              : 
     565              : /* First level of processing creates stack variables to be passed for further processing.
     566              :  * This is done to prevent multiple evaluations of input arguments (in case argument
     567              :  * evaluation has side effects, e.g. it is a non-pure function call).
     568              :  */
     569              : #define Z_LOG_MSG_CREATE2(_try_0cpy, _mode, _cstr_cnt,  _domain_id, _source, \
     570              :                            _level, _data, _dlen, ...) \
     571              : do { \
     572              :         FOR_EACH_IDX(Z_LOG_LOCAL_ARG_CREATE, (;), __VA_ARGS__); \
     573              :         Z_LOG_MSG_CREATE3(_try_0cpy, _mode,  _cstr_cnt, _domain_id, _source,\
     574              :                            _level, _data, _dlen, \
     575              :                            FOR_EACH_IDX(Z_LOG_LOCAL_ARG_NAME, (,), __VA_ARGS__)); \
     576              : } while (false)
     577              : #endif /* CONFIG_LOG_ALWAYS_RUNTIME || !CONFIG_LOG */
     578              : 
     579              : 
     580              : #define Z_LOG_MSG_CREATE(_try_0cpy, _mode,  _domain_id, _source,\
     581              :                           _level, _data, _dlen, ...) \
     582              :         Z_LOG_MSG_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
     583              :                            _domain_id, _source, _level, _data, _dlen, \
     584              :                            Z_LOG_STR(_level, __VA_ARGS__))
     585              : 
     586              : /** @brief Allocate log message.
     587              :  *
     588              :  * @param wlen Length in 32 bit words.
     589              :  *
     590              :  * @return allocated space or null if cannot be allocated.
     591              :  */
     592              : struct log_msg *z_log_msg_alloc(uint32_t wlen);
     593              : 
     594              : /** @brief Finalize message.
     595              :  *
     596              :  * Finalization includes setting source, copying data and timestamp in the
     597              :  * message followed by committing the message.
     598              :  *
     599              :  * @param msg Message.
     600              :  *
     601              :  * @param source Address of the source descriptor.
     602              :  *
     603              :  * @param desc Message descriptor.
     604              :  *
     605              :  * @param data Data.
     606              :  */
     607              : void z_log_msg_finalize(struct log_msg *msg, const void *source,
     608              :                          const struct log_msg_desc desc, const void *data);
     609              : 
     610              : /** @brief Create log message using simplified method for string with no arguments.
     611              :  *
     612              :  * @param source Pointer to the source structure.
     613              :  * @param level  Severity level.
     614              :  * @param fmt    String pointer.
     615              :  */
     616              : __syscall void z_log_msg_simple_create_0(const void *source, uint32_t level,
     617              :                                          const char *fmt);
     618              : 
     619              : /** @brief Create log message using simplified method for string with a one argument.
     620              :  *
     621              :  * @param source Pointer to the source structure.
     622              :  * @param level  Severity level.
     623              :  * @param fmt    String pointer.
     624              :  * @param arg    String argument.
     625              :  */
     626              : __syscall void z_log_msg_simple_create_1(const void *source, uint32_t level,
     627              :                                          const char *fmt, uint32_t arg);
     628              : 
     629              : /** @brief Create log message using simplified method for string with two arguments.
     630              :  *
     631              :  * @param source Pointer to the source structure.
     632              :  * @param level  Severity level.
     633              :  * @param fmt    String pointer.
     634              :  * @param arg0   String argument.
     635              :  * @param arg1   String argument.
     636              :  */
     637              : __syscall void z_log_msg_simple_create_2(const void *source, uint32_t level,
     638              :                                          const char *fmt, uint32_t arg0, uint32_t arg1);
     639              : 
     640              : /** @brief Create a logging message from message details and string package.
     641              :  *
     642              :  * @param source Source.
     643              :  *
     644              :  * @param desc Message descriptor.
     645              :  *
     646              :  * @param package Package.
     647              :  *
     648              :  * @param data Data.
     649              :  */
     650              : __syscall void z_log_msg_static_create(const void *source,
     651              :                                         const struct log_msg_desc desc,
     652              :                                         uint8_t *package, const void *data);
     653              : 
     654              : /** @brief Create message at runtime.
     655              :  *
     656              :  * Function allows to build any log message based on input data. Processing
     657              :  * time is significantly higher than statically message creating.
     658              :  *
     659              :  * @param domain_id Domain ID.
     660              :  *
     661              :  * @param source Source.
     662              :  *
     663              :  * @param level Log level.
     664              :  *
     665              :  * @param data Data.
     666              :  *
     667              :  * @param dlen Data length.
     668              :  *
     669              :  * @param package_flags Package flags.
     670              :  *
     671              :  * @param fmt String.
     672              :  *
     673              :  * @param ap Variable list of string arguments.
     674              :  */
     675              : void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source,
     676              :                                 uint8_t level, const void *data,
     677              :                                 size_t dlen, uint32_t package_flags,
     678              :                                 const char *fmt,
     679              :                                 va_list ap);
     680              : 
     681              : /** @brief Create message at runtime.
     682              :  *
     683              :  * Function allows to build any log message based on input data. Processing
     684              :  * time is significantly higher than statically message creating.
     685              :  *
     686              :  * @param domain_id Domain ID.
     687              :  *
     688              :  * @param source Source.
     689              :  *
     690              :  * @param level Log level.
     691              :  *
     692              :  * @param data Data.
     693              :  *
     694              :  * @param dlen Data length.
     695              :  *
     696              :  * @param package_flags Package flags.
     697              :  *
     698              :  * @param fmt String.
     699              :  *
     700              :  * @param ... String arguments.
     701              :  */
     702              : static inline void z_log_msg_runtime_create(uint8_t domain_id,
     703              :                                              const void *source,
     704              :                                              uint8_t level, const void *data,
     705              :                                              size_t dlen, uint32_t package_flags,
     706              :                                              const char *fmt, ...)
     707              : {
     708              :         va_list ap;
     709              : 
     710              :         va_start(ap, fmt);
     711              :         z_log_msg_runtime_vcreate(domain_id, source, level,
     712              :                                    data, dlen, package_flags, fmt, ap);
     713              :         va_end(ap);
     714              : }
     715              : 
     716              : static inline bool z_log_item_is_msg(const union log_msg_generic *msg)
     717              : {
     718              :         return msg->generic.type == Z_LOG_MSG_LOG;
     719              : }
     720              : 
     721              : /** @brief Get total length (in 32 bit words) of a log message.
     722              :  *
     723              :  * @param desc Log message descriptor.
     724              :  *
     725              :  * @return Length.
     726              :  */
     727            1 : static inline uint32_t log_msg_get_total_wlen(const struct log_msg_desc desc)
     728              : {
     729              :         return Z_LOG_MSG_ALIGNED_WLEN(desc.package_len, desc.data_len);
     730              : }
     731              : 
     732              : /** @brief Get length of the log item.
     733              :  *
     734              :  * @param item Item.
     735              :  *
     736              :  * @return Length in 32 bit words.
     737              :  */
     738            1 : static inline uint32_t log_msg_generic_get_wlen(const union mpsc_pbuf_generic *item)
     739              : {
     740              :         const union log_msg_generic *generic_msg = (const union log_msg_generic *)item;
     741              : 
     742              :         if (z_log_item_is_msg(generic_msg)) {
     743              :                 const struct log_msg *msg = (const struct log_msg *)generic_msg;
     744              : 
     745              :                 return log_msg_get_total_wlen(msg->hdr.desc);
     746              :         }
     747              : 
     748              :         return 0;
     749              : }
     750              : 
     751              : /** @brief Get log message domain ID.
     752              :  *
     753              :  * @param msg Log message.
     754              :  *
     755              :  * @return Domain ID
     756              :  */
     757            1 : static inline uint8_t log_msg_get_domain(struct log_msg *msg)
     758              : {
     759              :         return msg->hdr.desc.domain;
     760              : }
     761              : 
     762              : /** @brief Get log message level.
     763              :  *
     764              :  * @param msg Log message.
     765              :  *
     766              :  * @return Log level.
     767              :  */
     768            1 : static inline uint8_t log_msg_get_level(struct log_msg *msg)
     769              : {
     770              :         return msg->hdr.desc.level;
     771              : }
     772              : 
     773              : /** @brief Get message source data.
     774              :  *
     775              :  * @param msg Log message.
     776              :  *
     777              :  * @return Pointer to the source data.
     778              :  */
     779            1 : static inline const void *log_msg_get_source(struct log_msg *msg)
     780              : {
     781              :         return msg->hdr.source;
     782              : }
     783              : 
     784              : /** @brief Get log message source ID.
     785              :  *
     786              :  * @param msg Log message.
     787              :  *
     788              :  * @return Source ID, or -1 if not available.
     789              :  */
     790            1 : int16_t log_msg_get_source_id(struct log_msg *msg);
     791              : 
     792              : /** @brief Get timestamp.
     793              :  *
     794              :  * @param msg Log message.
     795              :  *
     796              :  * @return Timestamp.
     797              :  */
     798            1 : static inline log_timestamp_t log_msg_get_timestamp(struct log_msg *msg)
     799              : {
     800              :         return msg->hdr.timestamp;
     801              : }
     802              : 
     803              : /** @brief Get Thread ID.
     804              :  *
     805              :  * @param msg Log message.
     806              :  *
     807              :  * @return Thread ID.
     808              :  */
     809            1 : static inline void *log_msg_get_tid(struct log_msg *msg)
     810              : {
     811              : #if defined(CONFIG_LOG_THREAD_ID_PREFIX)
     812              :         return msg->hdr.tid;
     813              : #else
     814              :         ARG_UNUSED(msg);
     815              :         return NULL;
     816              : #endif
     817              : }
     818              : 
     819              : /** @brief Get data buffer.
     820              :  *
     821              :  * @param msg log message.
     822              :  *
     823              :  * @param len location where data length is written.
     824              :  *
     825              :  * @return pointer to the data buffer.
     826              :  */
     827            1 : static inline uint8_t *log_msg_get_data(struct log_msg *msg, size_t *len)
     828              : {
     829              :         *len = msg->hdr.desc.data_len;
     830              : 
     831              :         return msg->data + msg->hdr.desc.package_len;
     832              : }
     833              : 
     834              : /** @brief Get string package.
     835              :  *
     836              :  * @param msg log message.
     837              :  *
     838              :  * @param len location where string package length is written.
     839              :  *
     840              :  * @return pointer to the package.
     841              :  */
     842            1 : static inline uint8_t *log_msg_get_package(struct log_msg *msg, size_t *len)
     843              : {
     844              :         *len = msg->hdr.desc.package_len;
     845              : 
     846              :         return msg->data;
     847              : }
     848              : 
     849              : /**
     850              :  * @}
     851              :  */
     852              : 
     853              : #include <zephyr/syscalls/log_msg.h>
     854              : 
     855              : #ifdef __cplusplus
     856              : }
     857              : #endif
     858              : 
     859              : #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_ */
        

Generated by: LCOV version 2.0-1