LCOV - code coverage report
Current view: top level - zephyr/logging - log_msg.h Hit Total Coverage
Test: new.info Lines: 13 46 28.3 %
Date: 2024-12-22 00:14:23

          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_IGNORE_WSHADOW_BEGIN \
     340             :         struct log_msg *_msg; \
     341             :         TOOLCHAIN_IGNORE_WSHADOW_END \
     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) = (arg) + 0))
     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             :         _Pragma("GCC diagnostic push") \
     573             :         _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
     574             :         FOR_EACH_IDX(Z_LOG_LOCAL_ARG_CREATE, (;), __VA_ARGS__); \
     575             :         _Pragma("GCC diagnostic pop") \
     576             :         Z_LOG_MSG_CREATE3(_try_0cpy, _mode,  _cstr_cnt, _domain_id, _source,\
     577             :                            _level, _data, _dlen, \
     578             :                            FOR_EACH_IDX(Z_LOG_LOCAL_ARG_NAME, (,), __VA_ARGS__)); \
     579             : } while (false)
     580             : #endif /* CONFIG_LOG_ALWAYS_RUNTIME || !CONFIG_LOG */
     581             : 
     582             : 
     583             : #define Z_LOG_MSG_CREATE(_try_0cpy, _mode,  _domain_id, _source,\
     584             :                           _level, _data, _dlen, ...) \
     585             :         Z_LOG_MSG_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
     586             :                            _domain_id, _source, _level, _data, _dlen, \
     587             :                            Z_LOG_STR(_level, __VA_ARGS__))
     588             : 
     589             : /** @brief Allocate log message.
     590             :  *
     591             :  * @param wlen Length in 32 bit words.
     592             :  *
     593             :  * @return allocated space or null if cannot be allocated.
     594             :  */
     595             : struct log_msg *z_log_msg_alloc(uint32_t wlen);
     596             : 
     597             : /** @brief Finalize message.
     598             :  *
     599             :  * Finalization includes setting source, copying data and timestamp in the
     600             :  * message followed by committing the message.
     601             :  *
     602             :  * @param msg Message.
     603             :  *
     604             :  * @param source Address of the source descriptor.
     605             :  *
     606             :  * @param desc Message descriptor.
     607             :  *
     608             :  * @param data Data.
     609             :  */
     610             : void z_log_msg_finalize(struct log_msg *msg, const void *source,
     611             :                          const struct log_msg_desc desc, const void *data);
     612             : 
     613             : /** @brief Create log message using simplified method for string with no arguments.
     614             :  *
     615             :  * @param source Pointer to the source structure.
     616             :  * @param level  Severity level.
     617             :  * @param fmt    String pointer.
     618             :  */
     619             : __syscall void z_log_msg_simple_create_0(const void *source, uint32_t level,
     620             :                                          const char *fmt);
     621             : 
     622             : /** @brief Create log message using simplified method for string with a one argument.
     623             :  *
     624             :  * @param source Pointer to the source structure.
     625             :  * @param level  Severity level.
     626             :  * @param fmt    String pointer.
     627             :  * @param arg    String argument.
     628             :  */
     629             : __syscall void z_log_msg_simple_create_1(const void *source, uint32_t level,
     630             :                                          const char *fmt, uint32_t arg);
     631             : 
     632             : /** @brief Create log message using simplified method for string with two arguments.
     633             :  *
     634             :  * @param source Pointer to the source structure.
     635             :  * @param level  Severity level.
     636             :  * @param fmt    String pointer.
     637             :  * @param arg0   String argument.
     638             :  * @param arg1   String argument.
     639             :  */
     640             : __syscall void z_log_msg_simple_create_2(const void *source, uint32_t level,
     641             :                                          const char *fmt, uint32_t arg0, uint32_t arg1);
     642             : 
     643             : /** @brief Create a logging message from message details and string package.
     644             :  *
     645             :  * @param source Source.
     646             :  *
     647             :  * @param desc Message descriptor.
     648             :  *
     649             :  * @param package Package.
     650             :  *
     651             :  * @param data Data.
     652             :  */
     653             : __syscall void z_log_msg_static_create(const void *source,
     654             :                                         const struct log_msg_desc desc,
     655             :                                         uint8_t *package, const void *data);
     656             : 
     657             : /** @brief Create message at runtime.
     658             :  *
     659             :  * Function allows to build any log message based on input data. Processing
     660             :  * time is significantly higher than statically message creating.
     661             :  *
     662             :  * @param domain_id Domain ID.
     663             :  *
     664             :  * @param source Source.
     665             :  *
     666             :  * @param level Log level.
     667             :  *
     668             :  * @param data Data.
     669             :  *
     670             :  * @param dlen Data length.
     671             :  *
     672             :  * @param package_flags Package flags.
     673             :  *
     674             :  * @param fmt String.
     675             :  *
     676             :  * @param ap Variable list of string arguments.
     677             :  */
     678             : void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source,
     679             :                                 uint8_t level, const void *data,
     680             :                                 size_t dlen, uint32_t package_flags,
     681             :                                 const char *fmt,
     682             :                                 va_list ap);
     683             : 
     684             : /** @brief Create message at runtime.
     685             :  *
     686             :  * Function allows to build any log message based on input data. Processing
     687             :  * time is significantly higher than statically message creating.
     688             :  *
     689             :  * @param domain_id Domain ID.
     690             :  *
     691             :  * @param source Source.
     692             :  *
     693             :  * @param level Log level.
     694             :  *
     695             :  * @param data Data.
     696             :  *
     697             :  * @param dlen Data length.
     698             :  *
     699             :  * @param package_flags Package flags.
     700             :  *
     701             :  * @param fmt String.
     702             :  *
     703             :  * @param ... String arguments.
     704             :  */
     705             : static inline void z_log_msg_runtime_create(uint8_t domain_id,
     706             :                                              const void *source,
     707             :                                              uint8_t level, const void *data,
     708             :                                              size_t dlen, uint32_t package_flags,
     709             :                                              const char *fmt, ...)
     710             : {
     711             :         va_list ap;
     712             : 
     713             :         va_start(ap, fmt);
     714             :         z_log_msg_runtime_vcreate(domain_id, source, level,
     715             :                                    data, dlen, package_flags, fmt, ap);
     716             :         va_end(ap);
     717             : }
     718             : 
     719             : static inline bool z_log_item_is_msg(const union log_msg_generic *msg)
     720             : {
     721             :         return msg->generic.type == Z_LOG_MSG_LOG;
     722             : }
     723             : 
     724             : /** @brief Get total length (in 32 bit words) of a log message.
     725             :  *
     726             :  * @param desc Log message descriptor.
     727             :  *
     728             :  * @return Length.
     729             :  */
     730           1 : static inline uint32_t log_msg_get_total_wlen(const struct log_msg_desc desc)
     731             : {
     732             :         return Z_LOG_MSG_ALIGNED_WLEN(desc.package_len, desc.data_len);
     733             : }
     734             : 
     735             : /** @brief Get length of the log item.
     736             :  *
     737             :  * @param item Item.
     738             :  *
     739             :  * @return Length in 32 bit words.
     740             :  */
     741           1 : static inline uint32_t log_msg_generic_get_wlen(const union mpsc_pbuf_generic *item)
     742             : {
     743             :         const union log_msg_generic *generic_msg = (const union log_msg_generic *)item;
     744             : 
     745             :         if (z_log_item_is_msg(generic_msg)) {
     746             :                 const struct log_msg *msg = (const struct log_msg *)generic_msg;
     747             : 
     748             :                 return log_msg_get_total_wlen(msg->hdr.desc);
     749             :         }
     750             : 
     751             :         return 0;
     752             : }
     753             : 
     754             : /** @brief Get log message domain ID.
     755             :  *
     756             :  * @param msg Log message.
     757             :  *
     758             :  * @return Domain ID
     759             :  */
     760           1 : static inline uint8_t log_msg_get_domain(struct log_msg *msg)
     761             : {
     762             :         return msg->hdr.desc.domain;
     763             : }
     764             : 
     765             : /** @brief Get log message level.
     766             :  *
     767             :  * @param msg Log message.
     768             :  *
     769             :  * @return Log level.
     770             :  */
     771           1 : static inline uint8_t log_msg_get_level(struct log_msg *msg)
     772             : {
     773             :         return msg->hdr.desc.level;
     774             : }
     775             : 
     776             : /** @brief Get message source data.
     777             :  *
     778             :  * @param msg Log message.
     779             :  *
     780             :  * @return Pointer to the source data.
     781             :  */
     782           1 : static inline const void *log_msg_get_source(struct log_msg *msg)
     783             : {
     784             :         return msg->hdr.source;
     785             : }
     786             : 
     787             : /** @brief Get log message source ID.
     788             :  *
     789             :  * @param msg Log message.
     790             :  *
     791             :  * @return Source ID, or -1 if not available.
     792             :  */
     793           1 : int16_t log_msg_get_source_id(struct log_msg *msg);
     794             : 
     795             : /** @brief Get timestamp.
     796             :  *
     797             :  * @param msg Log message.
     798             :  *
     799             :  * @return Timestamp.
     800             :  */
     801           1 : static inline log_timestamp_t log_msg_get_timestamp(struct log_msg *msg)
     802             : {
     803             :         return msg->hdr.timestamp;
     804             : }
     805             : 
     806             : /** @brief Get Thread ID.
     807             :  *
     808             :  * @param msg Log message.
     809             :  *
     810             :  * @return Thread ID.
     811             :  */
     812           1 : static inline void *log_msg_get_tid(struct log_msg *msg)
     813             : {
     814             : #if defined(CONFIG_LOG_THREAD_ID_PREFIX)
     815             :         return msg->hdr.tid;
     816             : #else
     817             :         ARG_UNUSED(msg);
     818             :         return NULL;
     819             : #endif
     820             : }
     821             : 
     822             : /** @brief Get data buffer.
     823             :  *
     824             :  * @param msg log message.
     825             :  *
     826             :  * @param len location where data length is written.
     827             :  *
     828             :  * @return pointer to the data buffer.
     829             :  */
     830           1 : static inline uint8_t *log_msg_get_data(struct log_msg *msg, size_t *len)
     831             : {
     832             :         *len = msg->hdr.desc.data_len;
     833             : 
     834             :         return msg->data + msg->hdr.desc.package_len;
     835             : }
     836             : 
     837             : /** @brief Get string package.
     838             :  *
     839             :  * @param msg log message.
     840             :  *
     841             :  * @param len location where string package length is written.
     842             :  *
     843             :  * @return pointer to the package.
     844             :  */
     845           1 : static inline uint8_t *log_msg_get_package(struct log_msg *msg, size_t *len)
     846             : {
     847             :         *len = msg->hdr.desc.package_len;
     848             : 
     849             :         return msg->data;
     850             : }
     851             : 
     852             : /**
     853             :  * @}
     854             :  */
     855             : 
     856             : #include <zephyr/syscalls/log_msg.h>
     857             : 
     858             : #ifdef __cplusplus
     859             : }
     860             : #endif
     861             : 
     862             : #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_ */

Generated by: LCOV version 1.14