Fixing minor typos in comments Signed-off-by: Stefan Eicher <stefan.eicher@ypsomed.com> Signed-off-by: Anas Nashif <anas.nashif@intel.com>
619 lines
18 KiB
C
619 lines
18 KiB
C
/*
|
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_
|
|
#define ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_
|
|
|
|
#include <logging/log_instance.h>
|
|
#include <sys/mpsc_packet.h>
|
|
#include <sys/cbprintf.h>
|
|
#include <sys/atomic.h>
|
|
#include <sys/util.h>
|
|
#include <string.h>
|
|
|
|
#ifdef __GNUC__
|
|
#ifndef alloca
|
|
#define alloca __builtin_alloca
|
|
#endif
|
|
#else
|
|
#include <alloca.h>
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define LOG_MSG2_DEBUG 0
|
|
#define LOG_MSG2_DBG(...) IF_ENABLED(LOG_MSG2_DEBUG, (printk(__VA_ARGS__)))
|
|
|
|
#if CONFIG_LOG_TIMESTAMP_64BIT
|
|
typedef uint64_t log_timestamp_t;
|
|
#else
|
|
typedef uint32_t log_timestamp_t;
|
|
#endif
|
|
|
|
/**
|
|
* @brief Log message API
|
|
* @defgroup log_msg2 Log message v2 API
|
|
* @ingroup logger
|
|
* @{
|
|
*/
|
|
|
|
#define Z_LOG_MSG2_LOG 0
|
|
|
|
#define LOG_MSG2_GENERIC_HDR \
|
|
MPSC_PBUF_HDR;\
|
|
uint32_t type:1
|
|
|
|
struct log_msg2_desc {
|
|
LOG_MSG2_GENERIC_HDR;
|
|
uint32_t domain:3;
|
|
uint32_t level:3;
|
|
uint32_t package_len:10;
|
|
uint32_t data_len:12;
|
|
uint32_t reserved:1;
|
|
};
|
|
|
|
union log_msg2_source {
|
|
const struct log_source_const_data *fixed;
|
|
struct log_source_dynamic_data *dynamic;
|
|
void *raw;
|
|
};
|
|
|
|
struct log_msg2_hdr {
|
|
struct log_msg2_desc desc;
|
|
/* Attempting to keep best alignment. When address is 64 bit and timestamp 32
|
|
* swap the order to have 16 byte header instead of 24 byte.
|
|
*/
|
|
#if (INTPTR_MAX > INT32_MAX) && !CONFIG_LOG_TIMESTAMP_64BIT
|
|
log_timestamp_t timestamp;
|
|
const void *source;
|
|
#else
|
|
const void *source;
|
|
log_timestamp_t timestamp;
|
|
#endif
|
|
#if defined(__xtensa__) && !defined(CONFIG_LOG_TIMESTAMP_64BIT)
|
|
/* xtensa requires that cbprintf package that follows the header is
|
|
* aligned to 16 bytes. Adding padding when necessary.
|
|
*/
|
|
uint32_t padding;
|
|
#endif
|
|
};
|
|
|
|
struct log_msg2 {
|
|
struct log_msg2_hdr hdr;
|
|
uint8_t data[];
|
|
};
|
|
|
|
struct log_msg2_generic_hdr {
|
|
LOG_MSG2_GENERIC_HDR;
|
|
};
|
|
|
|
union log_msg2_generic {
|
|
union mpsc_pbuf_generic buf;
|
|
struct log_msg2_generic_hdr generic;
|
|
struct log_msg2 log;
|
|
};
|
|
|
|
/** @brief Method used for creating a log message.
|
|
*
|
|
* It is used for testing purposes to validate that expected mode was used.
|
|
*/
|
|
enum z_log_msg2_mode {
|
|
/* Runtime mode is least efficient but supports all cases thus it is
|
|
* treated as a fallback method when others cannot be used.
|
|
*/
|
|
Z_LOG_MSG2_MODE_RUNTIME,
|
|
/* Mode creates statically a string package on stack and calls a
|
|
* function for creating a message. It takes code size than
|
|
* Z_LOG_MSG2_MODE_ZERO_COPY but is a bit slower.
|
|
*/
|
|
Z_LOG_MSG2_MODE_FROM_STACK,
|
|
|
|
/* Mode calculates size of the message and allocates it and writes
|
|
* directly to the message space. It is the fastest method but requires
|
|
* more code size.
|
|
*/
|
|
Z_LOG_MSG2_MODE_ZERO_COPY,
|
|
|
|
/* Mode used when synchronous logging is enabled. */
|
|
Z_LOG_MSG2_MODE_SYNC
|
|
};
|
|
|
|
#define Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, _plen, _dlen) \
|
|
{ \
|
|
.valid = 0, \
|
|
.busy = 0, \
|
|
.type = Z_LOG_MSG2_LOG, \
|
|
.domain = _domain_id, \
|
|
.level = _level, \
|
|
.package_len = _plen, \
|
|
.data_len = _dlen, \
|
|
.reserved = 0, \
|
|
}
|
|
|
|
/* Messages are aligned to alignment required by cbprintf package. */
|
|
#define Z_LOG_MSG2_ALIGNMENT CBPRINTF_PACKAGE_ALIGNMENT
|
|
|
|
#if CONFIG_LOG2_USE_VLA
|
|
#define Z_LOG_MSG2_ON_STACK_ALLOC(ptr, len) \
|
|
long long _ll_buf[ceiling_fraction(len, sizeof(long long))]; \
|
|
long double _ld_buf[ceiling_fraction(len, sizeof(long double))]; \
|
|
ptr = (sizeof(long double) == Z_LOG_MSG2_ALIGNMENT) ? \
|
|
(struct log_msg2 *)_ld_buf : (struct log_msg2 *)_ll_buf; \
|
|
if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
|
|
/* During test fill with 0's to simplify message comparison */ \
|
|
memset(ptr, 0, len); \
|
|
}
|
|
#else /* Z_LOG_MSG2_USE_VLA */
|
|
/* When VLA cannot be used we need to trick compiler a bit and create multiple
|
|
* fixed size arrays and take the smallest one that will fit the message.
|
|
* Compiler will remove unused arrays and stack usage will be kept similar
|
|
* to vla case, rounded to the size of the used buffer.
|
|
*/
|
|
#define Z_LOG_MSG2_ON_STACK_ALLOC(ptr, len) \
|
|
long long _ll_buf32[32 / sizeof(long long)]; \
|
|
long long _ll_buf48[48 / sizeof(long long)]; \
|
|
long long _ll_buf64[64 / sizeof(long long)]; \
|
|
long long _ll_buf128[128 / sizeof(long long)]; \
|
|
long long _ll_buf256[256 / sizeof(long long)]; \
|
|
long double _ld_buf32[32 / sizeof(long double)]; \
|
|
long double _ld_buf48[48 / sizeof(long double)]; \
|
|
long double _ld_buf64[64 / sizeof(long double)]; \
|
|
long double _ld_buf128[128 / sizeof(long double)]; \
|
|
long double _ld_buf256[256 / sizeof(long double)]; \
|
|
if (sizeof(long double) == Z_LOG_MSG2_ALIGNMENT) { \
|
|
ptr = (len > 128) ? (struct log_msg2 *)_ld_buf256 : \
|
|
((len > 64) ? (struct log_msg2 *)_ld_buf128 : \
|
|
((len > 48) ? (struct log_msg2 *)_ld_buf64 : \
|
|
((len > 32) ? (struct log_msg2 *)_ld_buf48 : \
|
|
(struct log_msg2 *)_ld_buf32)));\
|
|
} else { \
|
|
ptr = (len > 128) ? (struct log_msg2 *)_ll_buf256 : \
|
|
((len > 64) ? (struct log_msg2 *)_ll_buf128 : \
|
|
((len > 48) ? (struct log_msg2 *)_ll_buf64 : \
|
|
((len > 32) ? (struct log_msg2 *)_ll_buf48 : \
|
|
(struct log_msg2 *)_ll_buf32)));\
|
|
} \
|
|
if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
|
|
/* During test fill with 0's to simplify message comparison */ \
|
|
memset(ptr, 0, len); \
|
|
}
|
|
#endif /* Z_LOG_MSG2_USE_VLA */
|
|
|
|
#define Z_LOG_MSG2_ALIGN_OFFSET \
|
|
sizeof(struct log_msg2_hdr)
|
|
|
|
#define Z_LOG_MSG2_LEN(pkg_len, data_len) \
|
|
(sizeof(struct log_msg2_hdr) + pkg_len + (data_len))
|
|
|
|
#define Z_LOG_MSG2_ALIGNED_WLEN(pkg_len, data_len) \
|
|
ceiling_fraction(ROUND_UP(Z_LOG_MSG2_LEN(pkg_len, data_len), \
|
|
Z_LOG_MSG2_ALIGNMENT), \
|
|
sizeof(uint32_t))
|
|
|
|
#define Z_LOG_MSG2_SYNC(_domain_id, _source, _level, _data, _dlen, ...) do { \
|
|
int _plen; \
|
|
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
struct log_msg2 *_msg; \
|
|
Z_LOG_MSG2_ON_STACK_ALLOC(_msg, Z_LOG_MSG2_LEN(_plen, _dlen)); \
|
|
if (_plen) {\
|
|
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
|
|
Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
} \
|
|
struct log_msg2_desc _desc = \
|
|
Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
|
|
(uint32_t)_plen, _dlen); \
|
|
z_log_msg2_finalize(_msg, _source, _desc, _data); \
|
|
} while (0)
|
|
|
|
#define Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, _dlen, ...)\
|
|
do { \
|
|
int _plen; \
|
|
if (GET_ARG_N(1, __VA_ARGS__) == NULL) { \
|
|
_plen = 0; \
|
|
} else { \
|
|
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
} \
|
|
struct log_msg2 *_msg; \
|
|
Z_LOG_MSG2_ON_STACK_ALLOC(_msg, Z_LOG_MSG2_LEN(_plen, 0)); \
|
|
if (_plen) { \
|
|
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, \
|
|
_plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__);\
|
|
} \
|
|
struct log_msg2_desc _desc = \
|
|
Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
|
|
(uint32_t)_plen, _dlen); \
|
|
LOG_MSG2_DBG("creating message on stack: package len: %d, data len: %d\n", \
|
|
_plen, (int)(_dlen)); \
|
|
z_log_msg2_static_create((void *)_source, _desc, _msg->data, _data); \
|
|
} while (0)
|
|
|
|
#if CONFIG_LOG_SPEED
|
|
#define Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, _level, ...) do { \
|
|
int _plen; \
|
|
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
size_t _msg_wlen = Z_LOG_MSG2_ALIGNED_WLEN(_plen, 0); \
|
|
struct log_msg2 *_msg = z_log_msg2_alloc(_msg_wlen); \
|
|
struct log_msg2_desc _desc = \
|
|
Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, (uint32_t)_plen, 0); \
|
|
LOG_MSG2_DBG("creating message zero copy: package len: %d, msg: %p\n", \
|
|
_plen, _msg); \
|
|
if (_msg) { \
|
|
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
|
|
Z_LOG_MSG2_ALIGN_OFFSET, \
|
|
0, __VA_ARGS__); \
|
|
} \
|
|
z_log_msg2_finalize(_msg, (void *)_source, _desc, NULL); \
|
|
} while (0)
|
|
#else
|
|
/* Alternative empty macro created to speed up compilation when LOG_SPEED is
|
|
* disabled (default).
|
|
*/
|
|
#define Z_LOG_MSG2_SIMPLE_CREATE(...)
|
|
#endif
|
|
|
|
/* Macro handles case when local variable with log message string is created.It
|
|
* replaces origing string literal with that variable.
|
|
*/
|
|
#define Z_LOG_FMT_ARGS_2(_name, ...) \
|
|
COND_CODE_1(CONFIG_LOG2_FMT_SECTION, \
|
|
(COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
|
|
(_name), (_name, GET_ARGS_LESS_N(1, __VA_ARGS__)))), \
|
|
(__VA_ARGS__))
|
|
|
|
/** @brief Wrapper for log message string with arguments.
|
|
*
|
|
* Wrapper is replacing first argument with a variable from a dedicated memory
|
|
* section if option is enabled. Macro handles the case when there is no
|
|
* log message provided.
|
|
*
|
|
* @param _name Name of the variable with log message string. It is optionally used.
|
|
* @param ... Optional log message with arguments (may be empty).
|
|
*/
|
|
#define Z_LOG_FMT_ARGS(_name, ...) \
|
|
COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
|
|
(NULL), \
|
|
(Z_LOG_FMT_ARGS_2(_name, ##__VA_ARGS__)))
|
|
|
|
/* Macro handles case when there is no string provided, in that case variable
|
|
* is not created.
|
|
*/
|
|
#define Z_LOG_MSG2_STR_VAR_IN_SECTION(_name, ...) \
|
|
COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
|
|
(/* No args provided, no variable */), \
|
|
(static const char _name[] \
|
|
__attribute__((__section__(".log_strings"))) = \
|
|
GET_ARG_N(1, __VA_ARGS__);))
|
|
|
|
/** @brief Create variable in the dedicated memory section (if enabled).
|
|
*
|
|
* Variable is initialized with a format string from the log message.
|
|
*
|
|
* @param _name Variable name.
|
|
* @param ... Optional log message with arguments (may be empty).
|
|
*/
|
|
#define Z_LOG_MSG2_STR_VAR(_name, ...) \
|
|
IF_ENABLED(CONFIG_LOG2_FMT_SECTION, \
|
|
(Z_LOG_MSG2_STR_VAR_IN_SECTION(_name, ##__VA_ARGS__)))
|
|
|
|
/** @brief Create log message and write it into the logger buffer.
|
|
*
|
|
* Macro handles creation of log message which includes storing log message
|
|
* description, timestamp, arguments, copying string arguments into message and
|
|
* copying user data into the message space. The are 3 modes of message
|
|
* creation:
|
|
* - at compile time message size is determined, message is allocated and
|
|
* content is written directly to the message. It is the fastest but cannot
|
|
* be used in user mode. Message size cannot be determined at compile time if
|
|
* it contains data or string arguments which are string pointers.
|
|
* - at compile time message size is determined, string package is created on
|
|
* stack, message is created in function call. String package can only be
|
|
* created on stack if it does not contain unexpected pointers to strings.
|
|
* - string package is created at runtime. This mode has no limitations but
|
|
* it is significantly slower.
|
|
*
|
|
* @param _try_0cpy If positive then, if possible, message content is written
|
|
* directly to message. If 0 then, if possible, string package is created on
|
|
* the stack and message is created in the function call.
|
|
*
|
|
* @param _mode Used for testing. It is set according to message creation mode
|
|
* used.
|
|
*
|
|
* @param _cstr_cnt Number of constant strings present in the string. It is
|
|
* used to help detect messages which must be runtime processed, compared to
|
|
* message which can be prebuilt at compile time.
|
|
*
|
|
* @param _domain_id Domain ID.
|
|
*
|
|
* @param _source Pointer to the constant descriptor of the log message source.
|
|
*
|
|
* @param _level Log message level.
|
|
*
|
|
* @param _data Pointer to the data. Can be null.
|
|
*
|
|
* @param _dlen Number of data bytes. 0 if data is not provided.
|
|
*
|
|
* @param ... Optional string with arguments (fmt, ...). It may be empty.
|
|
*/
|
|
#if CONFIG_LOG2_ALWAYS_RUNTIME
|
|
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
do {\
|
|
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__) \
|
|
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
|
_level, (uint8_t *)_data, _dlen,\
|
|
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
|
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
|
} while (0)
|
|
#elif CONFIG_LOG2_MODE_IMMEDIATE /* CONFIG_LOG2_ALWAYS_RUNTIME */
|
|
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
do { \
|
|
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
|
|
if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \
|
|
LOG_MSG2_DBG("create runtime message\n");\
|
|
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
|
_level, (uint8_t *)_data, _dlen,\
|
|
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
|
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
|
} else {\
|
|
Z_LOG_MSG2_SYNC(_domain_id, _source, _level, \
|
|
_data, _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
|
_mode = Z_LOG_MSG2_MODE_SYNC; \
|
|
} \
|
|
} while (0)
|
|
#else /* CONFIG_LOG2_ALWAYS_RUNTIME */
|
|
#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
do { \
|
|
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
|
|
if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \
|
|
LOG_MSG2_DBG("create runtime message\n");\
|
|
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
|
_level, (uint8_t *)_data, _dlen,\
|
|
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
|
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
|
} else if (IS_ENABLED(CONFIG_LOG_SPEED) && _try_0cpy && ((_dlen) == 0)) {\
|
|
LOG_MSG2_DBG("create zero-copy message\n");\
|
|
Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, \
|
|
_level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
|
_mode = Z_LOG_MSG2_MODE_ZERO_COPY; \
|
|
} else { \
|
|
LOG_MSG2_DBG("create on stack message\n");\
|
|
Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, \
|
|
_dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
|
_mode = Z_LOG_MSG2_MODE_FROM_STACK; \
|
|
} \
|
|
(void)_mode; \
|
|
} while (0)
|
|
#endif /* CONFIG_LOG2_ALWAYS_RUNTIME */
|
|
|
|
#define Z_LOG_MSG2_CREATE(_try_0cpy, _mode, _domain_id, _source,\
|
|
_level, _data, _dlen, ...) \
|
|
Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
|
|
_domain_id, _source, _level, _data, _dlen, \
|
|
Z_LOG_STR(_level, __VA_ARGS__))
|
|
|
|
/** @brief Allocate log message.
|
|
*
|
|
* @param wlen Length in 32 bit words.
|
|
*
|
|
* @return allocated space or null if cannot be allocated.
|
|
*/
|
|
struct log_msg2 *z_log_msg2_alloc(uint32_t wlen);
|
|
|
|
/** @brief Finalize message.
|
|
*
|
|
* Finalization includes setting source, copying data and timestamp in the
|
|
* message followed by committing the message.
|
|
*
|
|
* @param msg Message.
|
|
*
|
|
* @param source Address of the source descriptor.
|
|
*
|
|
* @param desc Message descriptor.
|
|
*
|
|
* @param data Data.
|
|
*/
|
|
void z_log_msg2_finalize(struct log_msg2 *msg, const void *source,
|
|
const struct log_msg2_desc desc, const void *data);
|
|
|
|
/** @brief Create simple message from message details and string package.
|
|
*
|
|
* @param source Source.
|
|
*
|
|
* @param desc Message descriptor.
|
|
*
|
|
* @param package Package.
|
|
*
|
|
* @oaram data Data.
|
|
*/
|
|
__syscall void z_log_msg2_static_create(const void *source,
|
|
const struct log_msg2_desc desc,
|
|
uint8_t *package, const void *data);
|
|
|
|
/** @brief Create message at runtime.
|
|
*
|
|
* Function allows to build any log message based on input data. Processing
|
|
* time is significantly higher than statically message creating.
|
|
*
|
|
* @param domain_id Domain ID.
|
|
*
|
|
* @param source Source.
|
|
*
|
|
* @param level Log level.
|
|
*
|
|
* @param data Data.
|
|
*
|
|
* @param dlen Data length.
|
|
*
|
|
* @param fmt String.
|
|
*
|
|
* @param ap Variable list of string arguments.
|
|
*/
|
|
__syscall void z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
|
uint8_t level, const void *data,
|
|
size_t dlen, const char *fmt,
|
|
va_list ap);
|
|
|
|
/** @brief Create message at runtime.
|
|
*
|
|
* Function allows to build any log message based on input data. Processing
|
|
* time is significantly higher than statically message creating.
|
|
*
|
|
* @param domain_id Domain ID.
|
|
*
|
|
* @param source Source.
|
|
*
|
|
* @param level Log level.
|
|
*
|
|
* @param data Data.
|
|
*
|
|
* @param dlen Data length.
|
|
*
|
|
* @param fmt String.
|
|
*
|
|
* @param ... String arguments.
|
|
*/
|
|
static inline void z_log_msg2_runtime_create(uint8_t domain_id,
|
|
const void *source,
|
|
uint8_t level, const void *data,
|
|
size_t dlen, const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
z_log_msg2_runtime_vcreate(domain_id, source, level,
|
|
data, dlen, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
static inline bool z_log_item_is_msg(union log_msg2_generic *msg)
|
|
{
|
|
return msg->generic.type == Z_LOG_MSG2_LOG;
|
|
}
|
|
|
|
/** @brief Get total length (in 32 bit words) of a log message.
|
|
*
|
|
* @param desc Log message descriptor.
|
|
*
|
|
* @return Length.
|
|
*/
|
|
static inline uint32_t log_msg2_get_total_wlen(const struct log_msg2_desc desc)
|
|
{
|
|
return Z_LOG_MSG2_ALIGNED_WLEN(desc.package_len, desc.data_len);
|
|
}
|
|
|
|
/** @brief Get length of the log item.
|
|
*
|
|
* @param item Item.
|
|
*
|
|
* @return Length in 32 bit words.
|
|
*/
|
|
static inline uint32_t log_msg2_generic_get_wlen(const union mpsc_pbuf_generic *item)
|
|
{
|
|
union log_msg2_generic *generic_msg = (union log_msg2_generic *)item;
|
|
|
|
if (z_log_item_is_msg(generic_msg)) {
|
|
struct log_msg2 *msg = (struct log_msg2 *)generic_msg;
|
|
|
|
return log_msg2_get_total_wlen(msg->hdr.desc);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** @brief Get log message domain ID.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Domain ID
|
|
*/
|
|
static inline uint8_t log_msg2_get_domain(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.desc.domain;
|
|
}
|
|
|
|
/** @brief Get log message level.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Log level.
|
|
*/
|
|
static inline uint8_t log_msg2_get_level(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.desc.level;
|
|
}
|
|
|
|
/** @brief Get message source data.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Pointer to the source data.
|
|
*/
|
|
static inline const void *log_msg2_get_source(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.source;
|
|
}
|
|
|
|
/** @brief Get timestamp.
|
|
*
|
|
* @param msg Log message.
|
|
*
|
|
* @return Timestamp.
|
|
*/
|
|
static inline log_timestamp_t log_msg2_get_timestamp(struct log_msg2 *msg)
|
|
{
|
|
return msg->hdr.timestamp;
|
|
}
|
|
|
|
/** @brief Get data buffer.
|
|
*
|
|
* @param msg log message.
|
|
*
|
|
* @param len location where data length is written.
|
|
*
|
|
* @return pointer to the data buffer.
|
|
*/
|
|
static inline uint8_t *log_msg2_get_data(struct log_msg2 *msg, size_t *len)
|
|
{
|
|
*len = msg->hdr.desc.data_len;
|
|
|
|
return msg->data + msg->hdr.desc.package_len;
|
|
}
|
|
|
|
/** @brief Get string package.
|
|
*
|
|
* @param msg log message.
|
|
*
|
|
* @param len location where string package length is written.
|
|
*
|
|
* @return pointer to the package.
|
|
*/
|
|
static inline uint8_t *log_msg2_get_package(struct log_msg2 *msg, size_t *len)
|
|
{
|
|
*len = msg->hdr.desc.package_len;
|
|
|
|
return msg->data;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#include <syscalls/log_msg2.h>
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_ */
|