Zephyr Project API 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
log_msg.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
12
13#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_
14#define ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_
15
18#include <zephyr/sys/cbprintf.h>
19#include <zephyr/sys/atomic.h>
21#include <zephyr/sys/util.h>
22#include <string.h>
23#include <zephyr/toolchain.h>
24
25#ifdef __GNUC__
26#ifndef alloca
27#define alloca __builtin_alloca
28#endif
29#else
30#include <alloca.h>
31#endif
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
38#define LOG_MSG_DEBUG 0
39#define LOG_MSG_DBG(...) IF_ENABLED(LOG_MSG_DEBUG, (printk(__VA_ARGS__)))
41
51#ifdef CONFIG_LOG_TIMESTAMP_64BIT
53#else
55#endif
56
63
65#define Z_LOG_MSG_LOG 0
66
67#define Z_LOG_MSG_PACKAGE_BITS 11
68
69#define Z_LOG_MSG_MAX_PACKAGE BIT_MASK(Z_LOG_MSG_PACKAGE_BITS)
70
71#define LOG_MSG_GENERIC_HDR \
72 MPSC_PBUF_HDR;\
73 uint32_t type:1
74
75struct log_msg_desc {
76 LOG_MSG_GENERIC_HDR;
77 uint32_t domain:3;
78 uint32_t level:3;
79 uint32_t package_len:Z_LOG_MSG_PACKAGE_BITS;
80 uint32_t data_len:12;
81};
82
83union log_msg_source {
84 const struct log_source_const_data *fixed;
85 struct log_source_dynamic_data *dynamic;
86 void *raw;
87};
88
89struct log_msg_hdr {
90 struct log_msg_desc desc;
91/* Attempting to keep best alignment. When address is 64 bit and timestamp 32
92 * swap the order to have 16 byte header instead of 24 byte.
93 */
94#if (INTPTR_MAX > INT32_MAX) && !defined(CONFIG_LOG_TIMESTAMP_64BIT)
95 log_timestamp_t timestamp;
96 const void *source;
97#else
98 const void *source;
99 log_timestamp_t timestamp;
100#endif
101#if defined(CONFIG_LOG_THREAD_ID_PREFIX)
102 void *tid;
103#endif
104#if defined(CONFIG_LOG_CORE_ID_PREFIX)
105 uint8_t core_id;
106#endif
107};
108/* Messages are aligned to alignment required by cbprintf package. */
109#define Z_LOG_MSG_ALIGNMENT CBPRINTF_PACKAGE_ALIGNMENT
110
111#define Z_LOG_MSG_PADDING \
112 ((sizeof(struct log_msg_hdr) % Z_LOG_MSG_ALIGNMENT) > 0 ? \
113 (Z_LOG_MSG_ALIGNMENT - (sizeof(struct log_msg_hdr) % Z_LOG_MSG_ALIGNMENT)) : \
114 0)
115
116struct log_msg {
117 struct log_msg_hdr hdr;
118 /* Adding padding to ensure that cbprintf package that follows is
119 * properly aligned.
120 */
121 uint8_t padding[Z_LOG_MSG_PADDING];
122 uint8_t data[];
123};
124
125BUILD_ASSERT(sizeof(struct log_msg) % Z_LOG_MSG_ALIGNMENT == 0,
126 "Log msg size must aligned");
127
128
129struct log_msg_generic_hdr {
130 LOG_MSG_GENERIC_HDR;
131};
132
133union log_msg_generic {
134 union mpsc_pbuf_generic buf;
135 struct log_msg_generic_hdr generic;
136 struct log_msg log;
137};
138
143enum z_log_msg_mode {
144 /* Runtime mode is least efficient but supports all cases thus it is
145 * treated as a fallback method when others cannot be used.
146 */
147 Z_LOG_MSG_MODE_RUNTIME,
148 /* Mode creates statically a string package on stack and calls a
149 * function for creating a message. It takes code size than
150 * Z_LOG_MSG_MODE_ZERO_COPY but is a bit slower.
151 */
152 Z_LOG_MSG_MODE_FROM_STACK,
153
154 /* Mode calculates size of the message and allocates it and writes
155 * directly to the message space. It is the fastest method but requires
156 * more code size.
157 */
158 Z_LOG_MSG_MODE_ZERO_COPY,
159
160 /* Mode optimized for simple messages with 0 to 2 32 bit word arguments.*/
161 Z_LOG_MSG_MODE_SIMPLE,
162};
163
164#define Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, _plen, _dlen) \
165{ \
166 .valid = 0, \
167 .busy = 0, \
168 .type = Z_LOG_MSG_LOG, \
169 .domain = (_domain_id), \
170 .level = (_level), \
171 .package_len = (_plen), \
172 .data_len = (_dlen), \
173}
174
175#define Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) \
176 (CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt) | \
177 (IS_ENABLED(CONFIG_LOG_MSG_APPEND_RO_STRING_LOC) ? \
178 CBPRINTF_PACKAGE_ADD_STRING_IDXS : 0))
179
180#ifdef CONFIG_LOG_USE_VLA
181#define Z_LOG_MSG_ON_STACK_ALLOC(ptr, len) \
182 long long _ll_buf[DIV_ROUND_UP(len, sizeof(long long))]; \
183 long double _ld_buf[DIV_ROUND_UP(len, sizeof(long double))]; \
184 (ptr) = (sizeof(long double) == Z_LOG_MSG_ALIGNMENT) ? \
185 (struct log_msg *)_ld_buf : (struct log_msg *)_ll_buf; \
186 if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
187 /* During test fill with 0's to simplify message comparison */ \
188 memset((ptr), 0, (len)); \
189 }
190#else /* Z_LOG_MSG_USE_VLA */
191/* When VLA cannot be used we need to trick compiler a bit and create multiple
192 * fixed size arrays and take the smallest one that will fit the message.
193 * Compiler will remove unused arrays and stack usage will be kept similar
194 * to vla case, rounded to the size of the used buffer.
195 */
196#define Z_LOG_MSG_ON_STACK_ALLOC(ptr, len) \
197 long long _ll_buf32[32 / sizeof(long long)]; \
198 long long _ll_buf48[48 / sizeof(long long)]; \
199 long long _ll_buf64[64 / sizeof(long long)]; \
200 long long _ll_buf128[128 / sizeof(long long)]; \
201 long long _ll_buf256[256 / sizeof(long long)]; \
202 long double _ld_buf32[32 / sizeof(long double)]; \
203 long double _ld_buf48[48 / sizeof(long double)]; \
204 long double _ld_buf64[64 / sizeof(long double)]; \
205 long double _ld_buf128[128 / sizeof(long double)]; \
206 long double _ld_buf256[256 / sizeof(long double)]; \
207 if (sizeof(long double) == Z_LOG_MSG_ALIGNMENT) { \
208 ptr = (len > 128) ? (struct log_msg *)_ld_buf256 : \
209 ((len > 64) ? (struct log_msg *)_ld_buf128 : \
210 ((len > 48) ? (struct log_msg *)_ld_buf64 : \
211 ((len > 32) ? (struct log_msg *)_ld_buf48 : \
212 (struct log_msg *)_ld_buf32)));\
213 } else { \
214 ptr = (len > 128) ? (struct log_msg *)_ll_buf256 : \
215 ((len > 64) ? (struct log_msg *)_ll_buf128 : \
216 ((len > 48) ? (struct log_msg *)_ll_buf64 : \
217 ((len > 32) ? (struct log_msg *)_ll_buf48 : \
218 (struct log_msg *)_ll_buf32)));\
219 } \
220 if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
221 /* During test fill with 0's to simplify message comparison */ \
222 memset((ptr), 0, (len)); \
223 }
224#endif /* Z_LOG_MSG_USE_VLA */
225
226#define Z_LOG_MSG_ALIGN_OFFSET \
227 offsetof(struct log_msg, data)
228
229#define Z_LOG_MSG_LEN(pkg_len, data_len) \
230 (offsetof(struct log_msg, data) + (pkg_len) + (data_len))
231
232#define Z_LOG_MSG_ALIGNED_WLEN(pkg_len, data_len) \
233 DIV_ROUND_UP(ROUND_UP(Z_LOG_MSG_LEN(pkg_len, data_len), \
234 Z_LOG_MSG_ALIGNMENT), \
235 sizeof(uint32_t))
236
237/*
238 * With Zephyr SDK 0.14.2, aarch64-zephyr-elf-gcc (10.3.0) fails to ensure $sp
239 * is below the active memory during message construction. As a result,
240 * interrupts happening in the middle of that process can end up smashing active
241 * data and causing a logging fault. Work around this by inserting a compiler
242 * barrier after the allocation and before any use to make sure GCC moves the
243 * stack pointer soon enough
244 */
245
246#define Z_LOG_ARM64_VLA_PROTECT() compiler_barrier()
247
248#define _LOG_MSG_SIMPLE_XXXX0 1
249#define _LOG_MSG_SIMPLE_XXXX1 1
250#define _LOG_MSG_SIMPLE_XXXX2 1
251
252/* Determine if amount of arguments (less than 3) qualifies to simple message. */
253#define LOG_MSG_SIMPLE_ARG_CNT_CHECK(...) \
254 COND_CODE_1(UTIL_CAT(_LOG_MSG_SIMPLE_XXXX, NUM_VA_ARGS_LESS_1(__VA_ARGS__)), (1), (0))
255
256/* Set of marcos used to determine if arguments type allows simplified message creation mode. */
257#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_0(fmt) 1
258#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_1(fmt, arg) Z_CBPRINTF_IS_WORD_NUM(arg)
259#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_2(fmt, arg0, arg1) \
260 Z_CBPRINTF_IS_WORD_NUM(arg0) && Z_CBPRINTF_IS_WORD_NUM(arg1)
261
266#define LOG_MSG_SIMPLE_ARG_TYPE_CHECK(...) \
267 UTIL_CAT(LOG_MSG_SIMPLE_ARG_TYPE_CHECK_, NUM_VA_ARGS_LESS_1(__VA_ARGS__))(__VA_ARGS__)
268
281#define LOG_MSG_SIMPLE_CHECK(...) \
282 COND_CODE_1(CONFIG_64BIT, (0), (\
283 COND_CODE_1(LOG_MSG_SIMPLE_ARG_CNT_CHECK(__VA_ARGS__), ( \
284 LOG_MSG_SIMPLE_ARG_TYPE_CHECK(__VA_ARGS__)), (0))))
285
286/* Helper macro for handing log with one argument. Macro casts the first argument to uint32_t. */
287#define Z_LOG_MSG_SIMPLE_CREATE_1(_source, _level, ...) \
288 z_log_msg_simple_create_1(_source, _level, GET_ARG_N(1, __VA_ARGS__), \
289 (uint32_t)(uintptr_t)GET_ARG_N(2, __VA_ARGS__))
290
291/* Helper macro for handing log with two arguments. Macro casts arguments to uint32_t.
292 */
293#define Z_LOG_MSG_SIMPLE_CREATE_2(_source, _level, ...) \
294 z_log_msg_simple_create_2(_source, _level, GET_ARG_N(1, __VA_ARGS__), \
295 (uint32_t)(uintptr_t)GET_ARG_N(2, __VA_ARGS__), \
296 (uint32_t)(uintptr_t)GET_ARG_N(3, __VA_ARGS__))
297
298/* Call specific function based on the number of arguments.
299 * Since up 2 to arguments are supported COND_CODE_0 and COND_CODE_1 can be used to
300 * handle all cases (0, 1 and 2 arguments). When tracing is enable then for each
301 * function a macro is create. The difference between function and macro is that
302 * macro is applied to any input arguments so we need to make sure that it is
303 * always called with proper number of arguments. For that it is wrapped around
304 * into another macro and dummy arguments to cover for cases when there is less
305 * arguments in a log call.
306 */
307#define Z_LOG_MSG_SIMPLE_FUNC2(arg_cnt, _source, _level, ...) \
308 COND_CODE_0(arg_cnt, \
309 (z_log_msg_simple_create_0(_source, _level, GET_ARG_N(1, __VA_ARGS__))), \
310 (COND_CODE_1(arg_cnt, ( \
311 Z_LOG_MSG_SIMPLE_CREATE_1(_source, _level, __VA_ARGS__, dummy) \
312 ), ( \
313 Z_LOG_MSG_SIMPLE_CREATE_2(_source, _level, __VA_ARGS__, dummy, dummy) \
314 ) \
315 )))
316
326#define LOG_MSG_SIMPLE_FUNC(_source, _level, ...) \
327 Z_LOG_MSG_SIMPLE_FUNC2(NUM_VA_ARGS_LESS_1(__VA_ARGS__), _source, _level, __VA_ARGS__)
328
339#define Z_LOG_MSG_SIMPLE_ARGS_CREATE(_domain_id, _source, _level, ...) \
340 IF_ENABLED(LOG_MSG_SIMPLE_ARG_CNT_CHECK(__VA_ARGS__), (\
341 LOG_MSG_SIMPLE_FUNC(_source, _level, __VA_ARGS__); \
342 ))
343
344#define Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, _dlen, ...) \
345do { \
346 int _plen; \
347 uint32_t _options = Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) | \
348 CBPRINTF_PACKAGE_ADD_RW_STR_POS; \
349 if (is_null_no_warn((void *)GET_ARG_N(1, __VA_ARGS__))) { \
350 _plen = 0; \
351 } else { \
352 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG_ALIGN_OFFSET, _options, \
353 __VA_ARGS__); \
354 /* When GCOV was enabled it was seen that compilation could fail here. */ \
355 /* Adding protection like this helps. It is compile time resolved code */ \
356 /* so has no impact on performance. */ \
357 if (_plen < 0) { \
358 break; \
359 } \
360 } \
361 TOOLCHAIN_DISABLE_WARNING(TOOLCHAIN_WARNING_SHADOW) \
362 struct log_msg *_msg; \
363 TOOLCHAIN_ENABLE_WARNING(TOOLCHAIN_WARNING_SHADOW) \
364 Z_LOG_MSG_ON_STACK_ALLOC(_msg, Z_LOG_MSG_LEN(_plen, 0)); \
365 Z_LOG_ARM64_VLA_PROTECT(); \
366 if (_plen != 0) { \
367 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, \
368 _plen, Z_LOG_MSG_ALIGN_OFFSET, _options, \
369 __VA_ARGS__);\
370 } \
371 struct log_msg_desc _desc = \
372 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
373 (uint32_t)_plen, _dlen); \
374 LOG_MSG_DBG("creating message on stack: package len: %d, data len: %d\n", \
375 _plen, (int)(_dlen)); \
376 z_log_msg_static_create((const void *)(_source), _desc, _msg->data, (_data)); \
377} while (false)
378
379#ifdef CONFIG_LOG_SPEED
380#define Z_LOG_MSG_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, _level, ...) do { \
381 int _plen; \
382 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG_ALIGN_OFFSET, \
383 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
384 __VA_ARGS__); \
385 size_t _msg_wlen = Z_LOG_MSG_ALIGNED_WLEN(_plen, 0); \
386 struct log_msg *_msg = z_log_msg_alloc(_msg_wlen); \
387 struct log_msg_desc _desc = \
388 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, (uint32_t)_plen, 0); \
389 LOG_MSG_DBG("creating message zero copy: package len: %d, msg: %p\n", \
390 _plen, _msg); \
391 if (_msg) { \
392 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
393 Z_LOG_MSG_ALIGN_OFFSET, \
394 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
395 __VA_ARGS__); \
396 } \
397 z_log_msg_finalize(_msg, (const void *)_source, _desc, NULL); \
398} while (false)
399#else
400/* Alternative empty macro created to speed up compilation when LOG_SPEED is
401 * disabled (default).
402 */
403#define Z_LOG_MSG_SIMPLE_CREATE(...)
404#endif
405
406/* Macro handles case when local variable with log message string is created. It
407 * replaces original string literal with that variable.
408 */
409#define Z_LOG_FMT_ARGS_2(_name, ...) \
410 COND_CODE_1(CONFIG_LOG_FMT_SECTION, \
411 (COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
412 (_name), (_name, GET_ARGS_LESS_N(1, __VA_ARGS__)))), \
413 (__VA_ARGS__))
414
424#define Z_LOG_FMT_ARGS(_name, ...) \
425 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
426 (NULL), \
427 (Z_LOG_FMT_ARGS_2(_name, ##__VA_ARGS__)))
428
429#if defined(CONFIG_LOG_USE_TAGGED_ARGUMENTS)
430
431#define Z_LOG_FMT_TAGGED_ARGS_2(_name, ...) \
432 COND_CODE_1(CONFIG_LOG_FMT_SECTION, \
433 (_name, Z_CBPRINTF_TAGGED_ARGS(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
434 GET_ARGS_LESS_N(1, __VA_ARGS__))), \
435 (GET_ARG_N(1, __VA_ARGS__), \
436 Z_CBPRINTF_TAGGED_ARGS(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
437 GET_ARGS_LESS_N(1, __VA_ARGS__))))
438
449#define Z_LOG_FMT_TAGGED_ARGS(_name, ...) \
450 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
451 (Z_CBPRINTF_TAGGED_ARGS(0)), \
452 (Z_LOG_FMT_TAGGED_ARGS_2(_name, ##__VA_ARGS__)))
453
454#define Z_LOG_FMT_RUNTIME_ARGS(...) \
455 Z_LOG_FMT_TAGGED_ARGS(__VA_ARGS__)
456
457#else
458
459#define Z_LOG_FMT_RUNTIME_ARGS(...) \
460 Z_LOG_FMT_ARGS(__VA_ARGS__)
461
462#endif /* CONFIG_LOG_USE_TAGGED_ARGUMENTS */
463
464/* Macro handles case when there is no string provided, in that case variable
465 * is not created.
466 */
467#define Z_LOG_MSG_STR_VAR_IN_SECTION(_name, ...) \
468 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
469 (/* No args provided, no variable */), \
470 (static const char _name[] \
471 __in_section(_log_strings, static, _CONCAT(_name, __COUNTER__)) \
472 __used __noasan = \
473 GET_ARG_N(1, __VA_ARGS__);))
474
482#define Z_LOG_MSG_STR_VAR(_name, ...) \
483 IF_ENABLED(CONFIG_LOG_FMT_SECTION, \
484 (Z_LOG_MSG_STR_VAR_IN_SECTION(_name, ##__VA_ARGS__)))
485
525#if defined(CONFIG_LOG_ALWAYS_RUNTIME) || !defined(CONFIG_LOG)
526#define Z_LOG_MSG_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
527 _level, _data, _dlen, ...) \
528do {\
529 Z_LOG_MSG_STR_VAR(_fmt, ##__VA_ARGS__) \
530 z_log_msg_runtime_create((_domain_id), (const void *)(_source), \
531 (_level), (const void *)(_data), (_dlen),\
532 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) | \
533 (IS_ENABLED(CONFIG_LOG_USE_TAGGED_ARGUMENTS) ? \
534 CBPRINTF_PACKAGE_ARGS_ARE_TAGGED : 0), \
535 Z_LOG_FMT_RUNTIME_ARGS(_fmt, ##__VA_ARGS__));\
536 (_mode) = Z_LOG_MSG_MODE_RUNTIME; \
537} while (false)
538#else /* CONFIG_LOG_ALWAYS_RUNTIME || !CONFIG_LOG */
539#define Z_LOG_MSG_CREATE3(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
540 _level, _data, _dlen, ...) \
541do { \
542 Z_LOG_MSG_STR_VAR(_fmt, ##__VA_ARGS__); \
543 bool has_rw_str = CBPRINTF_MUST_RUNTIME_PACKAGE( \
544 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
545 __VA_ARGS__); \
546 if (IS_ENABLED(CONFIG_LOG_SPEED) && (_try_0cpy) && ((_dlen) == 0) && !has_rw_str) {\
547 LOG_MSG_DBG("create zero-copy message\n");\
548 Z_LOG_MSG_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, \
549 _level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
550 (_mode) = Z_LOG_MSG_MODE_ZERO_COPY; \
551 } else { \
552 IF_ENABLED(UTIL_AND(IS_ENABLED(CONFIG_LOG_SIMPLE_MSG_OPTIMIZE), \
553 UTIL_AND(UTIL_NOT(_domain_id), UTIL_NOT(_cstr_cnt))), \
554 ( \
555 bool can_simple = LOG_MSG_SIMPLE_CHECK(__VA_ARGS__); \
556 if (can_simple && ((_dlen) == 0) && !k_is_user_context()) { \
557 compiler_barrier(); \
558 LOG_MSG_DBG("create fast message\n"); \
559 Z_LOG_MSG_SIMPLE_ARGS_CREATE(_domain_id, _source, _level, \
560 Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
561 _mode = Z_LOG_MSG_MODE_SIMPLE; \
562 break; \
563 } \
564 ) \
565 ) \
566 LOG_MSG_DBG("create on stack message\n");\
567 Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, \
568 _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
569 (_mode) = Z_LOG_MSG_MODE_FROM_STACK; \
570 } \
571 (void)(_mode); \
572} while (false)
573
574#if defined(__cplusplus)
575#define Z_AUTO_TYPE auto
576#else
577#define Z_AUTO_TYPE __auto_type
578#endif
579
580/* Macro for getting name of a local variable with the exception of the first argument
581 * which is a formatted string in log message.
582 */
583#define Z_LOG_LOCAL_ARG_NAME(idx, arg) COND_CODE_0(idx, (arg), (_v##idx))
584
585/* Create local variable from input variable (expect for the first (fmt) argument). */
586#define Z_LOG_LOCAL_ARG_CREATE(idx, arg) \
587 COND_CODE_0(idx, (), (Z_AUTO_TYPE Z_LOG_LOCAL_ARG_NAME(idx, arg) = Z_ARGIFY(arg)))
588
589/* First level of processing creates stack variables to be passed for further processing.
590 * This is done to prevent multiple evaluations of input arguments (in case argument
591 * evaluation has side effects, e.g. it is a non-pure function call).
592 */
593#define Z_LOG_MSG_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source, \
594 _level, _data, _dlen, ...) \
595do { \
596 FOR_EACH_IDX(Z_LOG_LOCAL_ARG_CREATE, (;), __VA_ARGS__); \
597 Z_LOG_MSG_CREATE3(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
598 _level, _data, _dlen, \
599 FOR_EACH_IDX(Z_LOG_LOCAL_ARG_NAME, (,), __VA_ARGS__)); \
600} while (false)
601#endif /* CONFIG_LOG_ALWAYS_RUNTIME || !CONFIG_LOG */
602
603
604#define Z_LOG_MSG_CREATE(_try_0cpy, _mode, _domain_id, _source,\
605 _level, _data, _dlen, ...) \
606 Z_LOG_MSG_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
607 _domain_id, _source, _level, _data, _dlen, \
608 Z_LOG_STR(_level, __VA_ARGS__))
609
616struct log_msg *z_log_msg_alloc(uint32_t wlen);
617
631void z_log_msg_finalize(struct log_msg *msg, const void *source,
632 const struct log_msg_desc desc, const void *data);
633
640__syscall void z_log_msg_simple_create_0(const void *source, uint32_t level,
641 const char *fmt);
642
650__syscall void z_log_msg_simple_create_1(const void *source, uint32_t level,
651 const char *fmt, uint32_t arg);
652
661__syscall void z_log_msg_simple_create_2(const void *source, uint32_t level,
662 const char *fmt, uint32_t arg0, uint32_t arg1);
663
674__syscall void z_log_msg_static_create(const void *source,
675 const struct log_msg_desc desc,
676 uint8_t *package, const void *data);
677
699void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source,
700 uint8_t level, const void *data,
701 size_t dlen, uint32_t package_flags,
702 const char *fmt,
703 va_list ap);
704
726static inline void z_log_msg_runtime_create(uint8_t domain_id,
727 const void *source,
728 uint8_t level, const void *data,
729 size_t dlen, uint32_t package_flags,
730 const char *fmt, ...)
731{
732 va_list ap;
733
734 va_start(ap, fmt);
735 z_log_msg_runtime_vcreate(domain_id, source, level,
736 data, dlen, package_flags, fmt, ap);
737 va_end(ap);
738}
739
740static inline bool z_log_item_is_msg(const union log_msg_generic *msg)
741{
742 return msg->generic.type == Z_LOG_MSG_LOG;
743}
744
746
753static inline uint32_t log_msg_get_total_wlen(const struct log_msg_desc desc)
754{
755 return Z_LOG_MSG_ALIGNED_WLEN(desc.package_len, desc.data_len);
756}
757
765{
766 const union log_msg_generic *generic_msg = (const union log_msg_generic *)item;
767
768 if (z_log_item_is_msg(generic_msg)) {
769 const struct log_msg *msg = (const struct log_msg *)generic_msg;
770
771 return log_msg_get_total_wlen(msg->hdr.desc);
772 }
773
774 return 0;
775}
776
783static inline uint8_t log_msg_get_domain(struct log_msg *msg)
784{
785 return msg->hdr.desc.domain;
786}
787
794static inline uint8_t log_msg_get_level(struct log_msg *msg)
795{
796 return msg->hdr.desc.level;
797}
798
805static inline const void *log_msg_get_source(struct log_msg *msg)
806{
807 return msg->hdr.source;
808}
809
816int16_t log_msg_get_source_id(struct log_msg *msg);
817
824static inline log_timestamp_t log_msg_get_timestamp(struct log_msg *msg)
825{
826 return msg->hdr.timestamp;
827}
828
835static inline void *log_msg_get_tid(struct log_msg *msg)
836{
837#if defined(CONFIG_LOG_THREAD_ID_PREFIX)
838 return msg->hdr.tid;
839#else
840 ARG_UNUSED(msg);
841 return NULL;
842#endif
843}
844
851static inline uint8_t log_msg_get_core_id(struct log_msg *msg)
852{
853#if defined(CONFIG_LOG_CORE_ID_PREFIX)
854 return msg->hdr.core_id;
855#else
856 ARG_UNUSED(msg);
857 return 0;
858#endif
859}
860
869static inline uint8_t *log_msg_get_data(struct log_msg *msg, size_t *len)
870{
871 *len = msg->hdr.desc.data_len;
872
873 return msg->data + msg->hdr.desc.package_len;
874}
875
884static inline uint8_t *log_msg_get_package(struct log_msg *msg, size_t *len)
885{
886 *len = msg->hdr.desc.package_len;
887
888 return msg->data;
889}
890
894
895#include <zephyr/syscalls/log_msg.h>
896
897#ifdef __cplusplus
898}
899#endif
900
901#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_ */
static const void * log_msg_get_source(struct log_msg *msg)
Get message source data.
Definition log_msg.h:805
int16_t log_msg_get_source_id(struct log_msg *msg)
Get log message source ID.
static uint8_t log_msg_get_level(struct log_msg *msg)
Get log message level.
Definition log_msg.h:794
static void * log_msg_get_tid(struct log_msg *msg)
Get Thread ID.
Definition log_msg.h:835
static uint8_t log_msg_get_domain(struct log_msg *msg)
Get log message domain ID.
Definition log_msg.h:783
static uint8_t log_msg_get_core_id(struct log_msg *msg)
Get Core ID.
Definition log_msg.h:851
static uint32_t log_msg_generic_get_wlen(const union mpsc_pbuf_generic *item)
Get length of the log item.
Definition log_msg.h:764
static uint32_t log_msg_get_total_wlen(const struct log_msg_desc desc)
Get total length (in 32 bit words) of a log message.
Definition log_msg.h:753
uint32_t log_timestamp_t
Timestamp value associated with a log message.
Definition log_msg.h:54
static uint8_t * log_msg_get_package(struct log_msg *msg, size_t *len)
Get string package.
Definition log_msg.h:884
static log_timestamp_t log_msg_get_timestamp(struct log_msg *msg)
Get timestamp.
Definition log_msg.h:824
static uint8_t * log_msg_get_data(struct log_msg *msg, size_t *len)
Get data buffer.
Definition log_msg.h:869
#define NULL
Definition iar_missing_defs.h:20
#define BUILD_ASSERT(EXPR, MSG...)
Definition llvm.h:51
Header file for log instance registration.
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT64_TYPE__ uint64_t
Definition stdint.h:91
__UINT8_TYPE__ uint8_t
Definition stdint.h:88
__INT16_TYPE__ int16_t
Definition stdint.h:73
Header file for the Atomic operations API.
Iterable sections helpers.
Misc utilities.
Macros to abstract toolchain specific capabilities.
Generic packet header.
Definition mpsc_packet.h:49