1 /*
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 #define LOG_MSG_DEBUG 0
31 #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 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 #define LOG_MSG_GENERIC_HDR \
53 MPSC_PBUF_HDR;\
54 uint32_t type:1
55
56 struct log_msg_desc {
57 LOG_MSG_GENERIC_HDR;
58 uint32_t domain:3;
59 uint32_t level:3;
60 uint32_t package_len:Z_LOG_MSG_PACKAGE_BITS;
61 uint32_t data_len:12;
62 };
63
64 union log_msg_source {
65 const struct log_source_const_data *fixed;
66 struct log_source_dynamic_data *dynamic;
67 void *raw;
68 };
69
70 struct log_msg_hdr {
71 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) && !CONFIG_LOG_TIMESTAMP_64BIT
76 log_timestamp_t timestamp;
77 const void *source;
78 #else
79 const void *source;
80 log_timestamp_t timestamp;
81 #endif
82 };
83
84 /* Messages are aligned to alignment required by cbprintf package. */
85 #define Z_LOG_MSG_ALIGNMENT CBPRINTF_PACKAGE_ALIGNMENT
86
87 #define Z_LOG_MSG_PADDING \
88 ((sizeof(struct log_msg_hdr) % Z_LOG_MSG_ALIGNMENT) > 0 ? \
89 (Z_LOG_MSG_ALIGNMENT - (sizeof(struct log_msg_hdr) % Z_LOG_MSG_ALIGNMENT)) : \
90 0)
91
92 struct log_msg {
93 struct log_msg_hdr hdr;
94 /* Adding padding to ensure that cbprintf package that follows is
95 * properly aligned.
96 */
97 uint8_t padding[Z_LOG_MSG_PADDING];
98 uint8_t data[];
99 };
100
101 /**
102 * @cond INTERNAL_HIDDEN
103 */
104 BUILD_ASSERT(sizeof(struct log_msg) % Z_LOG_MSG_ALIGNMENT == 0,
105 "Log msg size must aligned");
106 /**
107 * @endcond
108 */
109
110
111 struct log_msg_generic_hdr {
112 LOG_MSG_GENERIC_HDR;
113 };
114
115 union log_msg_generic {
116 union mpsc_pbuf_generic buf;
117 struct log_msg_generic_hdr generic;
118 struct log_msg log;
119 };
120
121 /** @brief Method used for creating a log message.
122 *
123 * It is used for testing purposes to validate that expected mode was used.
124 */
125 enum z_log_msg_mode {
126 /* Runtime mode is least efficient but supports all cases thus it is
127 * treated as a fallback method when others cannot be used.
128 */
129 Z_LOG_MSG_MODE_RUNTIME,
130 /* Mode creates statically a string package on stack and calls a
131 * function for creating a message. It takes code size than
132 * Z_LOG_MSG_MODE_ZERO_COPY but is a bit slower.
133 */
134 Z_LOG_MSG_MODE_FROM_STACK,
135
136 /* Mode calculates size of the message and allocates it and writes
137 * directly to the message space. It is the fastest method but requires
138 * more code size.
139 */
140 Z_LOG_MSG_MODE_ZERO_COPY,
141 };
142
143 #define Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, _plen, _dlen) \
144 { \
145 .valid = 0, \
146 .busy = 0, \
147 .type = Z_LOG_MSG_LOG, \
148 .domain = _domain_id, \
149 .level = _level, \
150 .package_len = _plen, \
151 .data_len = _dlen, \
152 }
153
154 #define Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) \
155 (CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt) | \
156 (IS_ENABLED(CONFIG_LOG_MSG_APPEND_RO_STRING_LOC) ? \
157 CBPRINTF_PACKAGE_ADD_STRING_IDXS : 0))
158
159 #ifdef CONFIG_LOG_USE_VLA
160 #define Z_LOG_MSG_ON_STACK_ALLOC(ptr, len) \
161 long long _ll_buf[DIV_ROUND_UP(len, sizeof(long long))]; \
162 long double _ld_buf[DIV_ROUND_UP(len, sizeof(long double))]; \
163 ptr = (sizeof(long double) == Z_LOG_MSG_ALIGNMENT) ? \
164 (struct log_msg *)_ld_buf : (struct log_msg *)_ll_buf; \
165 if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
166 /* During test fill with 0's to simplify message comparison */ \
167 memset(ptr, 0, len); \
168 }
169 #else /* Z_LOG_MSG_USE_VLA */
170 /* When VLA cannot be used we need to trick compiler a bit and create multiple
171 * fixed size arrays and take the smallest one that will fit the message.
172 * Compiler will remove unused arrays and stack usage will be kept similar
173 * to vla case, rounded to the size of the used buffer.
174 */
175 #define Z_LOG_MSG_ON_STACK_ALLOC(ptr, len) \
176 long long _ll_buf32[32 / sizeof(long long)]; \
177 long long _ll_buf48[48 / sizeof(long long)]; \
178 long long _ll_buf64[64 / sizeof(long long)]; \
179 long long _ll_buf128[128 / sizeof(long long)]; \
180 long long _ll_buf256[256 / sizeof(long long)]; \
181 long double _ld_buf32[32 / sizeof(long double)]; \
182 long double _ld_buf48[48 / sizeof(long double)]; \
183 long double _ld_buf64[64 / sizeof(long double)]; \
184 long double _ld_buf128[128 / sizeof(long double)]; \
185 long double _ld_buf256[256 / sizeof(long double)]; \
186 if (sizeof(long double) == Z_LOG_MSG_ALIGNMENT) { \
187 ptr = (len > 128) ? (struct log_msg *)_ld_buf256 : \
188 ((len > 64) ? (struct log_msg *)_ld_buf128 : \
189 ((len > 48) ? (struct log_msg *)_ld_buf64 : \
190 ((len > 32) ? (struct log_msg *)_ld_buf48 : \
191 (struct log_msg *)_ld_buf32)));\
192 } else { \
193 ptr = (len > 128) ? (struct log_msg *)_ll_buf256 : \
194 ((len > 64) ? (struct log_msg *)_ll_buf128 : \
195 ((len > 48) ? (struct log_msg *)_ll_buf64 : \
196 ((len > 32) ? (struct log_msg *)_ll_buf48 : \
197 (struct log_msg *)_ll_buf32)));\
198 } \
199 if (IS_ENABLED(CONFIG_LOG_TEST_CLEAR_MESSAGE_SPACE)) { \
200 /* During test fill with 0's to simplify message comparison */ \
201 memset(ptr, 0, len); \
202 }
203 #endif /* Z_LOG_MSG_USE_VLA */
204
205 #define Z_LOG_MSG_ALIGN_OFFSET \
206 offsetof(struct log_msg, data)
207
208 #define Z_LOG_MSG_LEN(pkg_len, data_len) \
209 (offsetof(struct log_msg, data) + pkg_len + (data_len))
210
211 #define Z_LOG_MSG_ALIGNED_WLEN(pkg_len, data_len) \
212 DIV_ROUND_UP(ROUND_UP(Z_LOG_MSG_LEN(pkg_len, data_len), \
213 Z_LOG_MSG_ALIGNMENT), \
214 sizeof(uint32_t))
215
216 /*
217 * With Zephyr SDK 0.14.2, aarch64-zephyr-elf-gcc (10.3.0) fails to ensure $sp
218 * is below the active memory during message construction. As a result,
219 * interrupts happening in the middle of that process can end up smashing active
220 * data and causing a logging fault. Work around this by inserting a compiler
221 * barrier after the allocation and before any use to make sure GCC moves the
222 * stack pointer soon enough
223 */
224
225 #define Z_LOG_ARM64_VLA_PROTECT() compiler_barrier()
226
227 #define Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, _dlen, ...) \
228 do { \
229 int _plen; \
230 uint32_t _options = Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) | \
231 CBPRINTF_PACKAGE_ADD_RW_STR_POS; \
232 if (GET_ARG_N(1, __VA_ARGS__) == NULL) { \
233 _plen = 0; \
234 } else { \
235 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG_ALIGN_OFFSET, _options, \
236 __VA_ARGS__); \
237 } \
238 struct log_msg *_msg; \
239 Z_LOG_MSG_ON_STACK_ALLOC(_msg, Z_LOG_MSG_LEN(_plen, 0)); \
240 Z_LOG_ARM64_VLA_PROTECT(); \
241 if (_plen != 0) { \
242 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, \
243 _plen, Z_LOG_MSG_ALIGN_OFFSET, _options, \
244 __VA_ARGS__);\
245 } \
246 struct log_msg_desc _desc = \
247 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
248 (uint32_t)_plen, _dlen); \
249 LOG_MSG_DBG("creating message on stack: package len: %d, data len: %d\n", \
250 _plen, (int)(_dlen)); \
251 z_log_msg_static_create((void *)_source, _desc, _msg->data, _data); \
252 } while (false)
253
254 #ifdef CONFIG_LOG_SPEED
255 #define Z_LOG_MSG_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, _level, ...) do { \
256 int _plen; \
257 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG_ALIGN_OFFSET, \
258 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
259 __VA_ARGS__); \
260 size_t _msg_wlen = Z_LOG_MSG_ALIGNED_WLEN(_plen, 0); \
261 struct log_msg *_msg = z_log_msg_alloc(_msg_wlen); \
262 struct log_msg_desc _desc = \
263 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, (uint32_t)_plen, 0); \
264 LOG_MSG_DBG("creating message zero copy: package len: %d, msg: %p\n", \
265 _plen, _msg); \
266 if (_msg) { \
267 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
268 Z_LOG_MSG_ALIGN_OFFSET, \
269 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
270 __VA_ARGS__); \
271 } \
272 z_log_msg_finalize(_msg, (void *)_source, _desc, NULL); \
273 } while (false)
274 #else
275 /* Alternative empty macro created to speed up compilation when LOG_SPEED is
276 * disabled (default).
277 */
278 #define Z_LOG_MSG_SIMPLE_CREATE(...)
279 #endif
280
281 /* Macro handles case when local variable with log message string is created. It
282 * replaces original string literal with that variable.
283 */
284 #define Z_LOG_FMT_ARGS_2(_name, ...) \
285 COND_CODE_1(CONFIG_LOG_FMT_SECTION, \
286 (COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
287 (_name), (_name, GET_ARGS_LESS_N(1, __VA_ARGS__)))), \
288 (__VA_ARGS__))
289
290 /** @brief Wrapper for log message string with arguments.
291 *
292 * Wrapper is replacing first argument with a variable from a dedicated memory
293 * section if option is enabled. Macro handles the case when there is no
294 * log message provided.
295 *
296 * @param _name Name of the variable with log message string. It is optionally used.
297 * @param ... Optional log message with arguments (may be empty).
298 */
299 #define Z_LOG_FMT_ARGS(_name, ...) \
300 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
301 (NULL), \
302 (Z_LOG_FMT_ARGS_2(_name, ##__VA_ARGS__)))
303
304 #if defined(CONFIG_LOG_USE_TAGGED_ARGUMENTS)
305
306 #define Z_LOG_FMT_TAGGED_ARGS_2(_name, ...) \
307 COND_CODE_1(CONFIG_LOG_FMT_SECTION, \
308 (_name, Z_CBPRINTF_TAGGED_ARGS(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
309 GET_ARGS_LESS_N(1, __VA_ARGS__))), \
310 (GET_ARG_N(1, __VA_ARGS__), \
311 Z_CBPRINTF_TAGGED_ARGS(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
312 GET_ARGS_LESS_N(1, __VA_ARGS__))))
313
314 /** @brief Wrapper for log message string with tagged arguments.
315 *
316 * Wrapper is replacing first argument with a variable from a dedicated memory
317 * section if option is enabled. Macro handles the case when there is no
318 * log message provided. Each subsequent arguments are tagged by preceding
319 * each argument with its type value.
320 *
321 * @param _name Name of the variable with log message string. It is optionally used.
322 * @param ... Optional log message with arguments (may be empty).
323 */
324 #define Z_LOG_FMT_TAGGED_ARGS(_name, ...) \
325 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
326 (Z_CBPRINTF_TAGGED_ARGS(0)), \
327 (Z_LOG_FMT_TAGGED_ARGS_2(_name, ##__VA_ARGS__)))
328
329 #define Z_LOG_FMT_RUNTIME_ARGS(...) \
330 Z_LOG_FMT_TAGGED_ARGS(__VA_ARGS__)
331
332 #else
333
334 #define Z_LOG_FMT_RUNTIME_ARGS(...) \
335 Z_LOG_FMT_ARGS(__VA_ARGS__)
336
337 #endif /* CONFIG_LOG_USE_TAGGED_ARGUMENTS */
338
339 /* Macro handles case when there is no string provided, in that case variable
340 * is not created.
341 */
342 #define Z_LOG_MSG_STR_VAR_IN_SECTION(_name, ...) \
343 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
344 (/* No args provided, no variable */), \
345 (static const char _name[] \
346 __in_section(_log_strings, static, _CONCAT(_name, _)) __used __noasan = \
347 GET_ARG_N(1, __VA_ARGS__);))
348
349 /** @brief Create variable in the dedicated memory section (if enabled).
350 *
351 * Variable is initialized with a format string from the log message.
352 *
353 * @param _name Variable name.
354 * @param ... Optional log message with arguments (may be empty).
355 */
356 #define Z_LOG_MSG_STR_VAR(_name, ...) \
357 IF_ENABLED(CONFIG_LOG_FMT_SECTION, \
358 (Z_LOG_MSG_STR_VAR_IN_SECTION(_name, ##__VA_ARGS__)))
359
360 /** @brief Create log message and write it into the logger buffer.
361 *
362 * Macro handles creation of log message which includes storing log message
363 * description, timestamp, arguments, copying string arguments into message and
364 * copying user data into the message space. The are 3 modes of message
365 * creation:
366 * - at compile time message size is determined, message is allocated and
367 * content is written directly to the message. It is the fastest but cannot
368 * be used in user mode. Message size cannot be determined at compile time if
369 * it contains data or string arguments which are string pointers.
370 * - at compile time message size is determined, string package is created on
371 * stack, message is created in function call. String package can only be
372 * created on stack if it does not contain unexpected pointers to strings.
373 * - string package is created at runtime. This mode has no limitations but
374 * it is significantly slower.
375 *
376 * @param _try_0cpy If positive then, if possible, message content is written
377 * directly to message. If 0 then, if possible, string package is created on
378 * the stack and message is created in the function call.
379 *
380 * @param _mode Used for testing. It is set according to message creation mode
381 * used.
382 *
383 * @param _cstr_cnt Number of constant strings present in the string. It is
384 * used to help detect messages which must be runtime processed, compared to
385 * message which can be prebuilt at compile time.
386 *
387 * @param _domain_id Domain ID.
388 *
389 * @param _source Pointer to the constant descriptor of the log message source.
390 *
391 * @param _level Log message level.
392 *
393 * @param _data Pointer to the data. Can be null.
394 *
395 * @param _dlen Number of data bytes. 0 if data is not provided.
396 *
397 * @param ... Optional string with arguments (fmt, ...). It may be empty.
398 */
399 #if defined(CONFIG_LOG_ALWAYS_RUNTIME) || \
400 (!defined(CONFIG_LOG) && \
401 (!TOOLCHAIN_HAS_PRAGMA_DIAG || !TOOLCHAIN_HAS_C_AUTO_TYPE))
402 #define Z_LOG_MSG_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
403 _level, _data, _dlen, ...) \
404 do {\
405 Z_LOG_MSG_STR_VAR(_fmt, ##__VA_ARGS__) \
406 z_log_msg_runtime_create(_domain_id, (void *)_source, \
407 _level, (uint8_t *)_data, _dlen,\
408 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt) | \
409 (IS_ENABLED(CONFIG_LOG_USE_TAGGED_ARGUMENTS) ? \
410 CBPRINTF_PACKAGE_ARGS_ARE_TAGGED : 0), \
411 Z_LOG_FMT_RUNTIME_ARGS(_fmt, ##__VA_ARGS__));\
412 _mode = Z_LOG_MSG_MODE_RUNTIME; \
413 } while (false)
414 #else /* CONFIG_LOG_ALWAYS_RUNTIME */
415 #define Z_LOG_MSG_CREATE3(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
416 _level, _data, _dlen, ...) \
417 do { \
418 Z_LOG_MSG_STR_VAR(_fmt, ##__VA_ARGS__); \
419 bool has_rw_str = CBPRINTF_MUST_RUNTIME_PACKAGE( \
420 Z_LOG_MSG_CBPRINTF_FLAGS(_cstr_cnt), \
421 __VA_ARGS__); \
422 if (IS_ENABLED(CONFIG_LOG_SPEED) && _try_0cpy && ((_dlen) == 0) && !has_rw_str) {\
423 LOG_MSG_DBG("create zero-copy message\n");\
424 Z_LOG_MSG_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, \
425 _level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
426 _mode = Z_LOG_MSG_MODE_ZERO_COPY; \
427 } else { \
428 LOG_MSG_DBG("create on stack message\n");\
429 Z_LOG_MSG_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, \
430 _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
431 _mode = Z_LOG_MSG_MODE_FROM_STACK; \
432 } \
433 (void)_mode; \
434 } while (false)
435
436 #if defined(__cplusplus)
437 #define Z_AUTO_TYPE auto
438 #else
439 #define Z_AUTO_TYPE __auto_type
440 #endif
441
442 /* Macro for getting name of a local variable with the exception of the first argument
443 * which is a formatted string in log message.
444 */
445 #define Z_LOG_LOCAL_ARG_NAME(idx, arg) COND_CODE_0(idx, (arg), (_v##idx))
446
447 /* Create local variable from input variable (expect for the first (fmt) argument). */
448 #define Z_LOG_LOCAL_ARG_CREATE(idx, arg) \
449 COND_CODE_0(idx, (), (Z_AUTO_TYPE Z_LOG_LOCAL_ARG_NAME(idx, arg) = (arg) + 0))
450
451 /* First level of processing creates stack variables to be passed for further processing.
452 * This is done to prevent multiple evaluations of input arguments (in case argument
453 * evaluation has side effects, e.g. it is a non-pure function call).
454 */
455 #define Z_LOG_MSG_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source, \
456 _level, _data, _dlen, ...) \
457 do { \
458 _Pragma("GCC diagnostic push") \
459 _Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
460 FOR_EACH_IDX(Z_LOG_LOCAL_ARG_CREATE, (;), __VA_ARGS__); \
461 _Pragma("GCC diagnostic pop") \
462 Z_LOG_MSG_CREATE3(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
463 _level, _data, _dlen, \
464 FOR_EACH_IDX(Z_LOG_LOCAL_ARG_NAME, (,), __VA_ARGS__)); \
465 } while (false)
466 #endif /* CONFIG_LOG_ALWAYS_RUNTIME ||
467 * (!LOG && (!TOOLCHAIN_HAS_PRAGMA_DIAG || !TOOLCHAIN_HAS_C_AUTO_TYPE))
468 */
469
470
471 #define Z_LOG_MSG_CREATE(_try_0cpy, _mode, _domain_id, _source,\
472 _level, _data, _dlen, ...) \
473 Z_LOG_MSG_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
474 _domain_id, _source, _level, _data, _dlen, \
475 Z_LOG_STR(_level, __VA_ARGS__))
476
477 /** @brief Allocate log message.
478 *
479 * @param wlen Length in 32 bit words.
480 *
481 * @return allocated space or null if cannot be allocated.
482 */
483 struct log_msg *z_log_msg_alloc(uint32_t wlen);
484
485 /** @brief Finalize message.
486 *
487 * Finalization includes setting source, copying data and timestamp in the
488 * message followed by committing the message.
489 *
490 * @param msg Message.
491 *
492 * @param source Address of the source descriptor.
493 *
494 * @param desc Message descriptor.
495 *
496 * @param data Data.
497 */
498 void z_log_msg_finalize(struct log_msg *msg, const void *source,
499 const struct log_msg_desc desc, const void *data);
500
501 /** @brief Create simple message from message details and string package.
502 *
503 * @param source Source.
504 *
505 * @param desc Message descriptor.
506 *
507 * @param package Package.
508 *
509 * @oaram data Data.
510 */
511 __syscall void z_log_msg_static_create(const void *source,
512 const struct log_msg_desc desc,
513 uint8_t *package, const void *data);
514
515 /** @brief Create message at runtime.
516 *
517 * Function allows to build any log message based on input data. Processing
518 * time is significantly higher than statically message creating.
519 *
520 * @param domain_id Domain ID.
521 *
522 * @param source Source.
523 *
524 * @param level Log level.
525 *
526 * @param data Data.
527 *
528 * @param dlen Data length.
529 *
530 * @param package_flags Package flags.
531 *
532 * @param fmt String.
533 *
534 * @param ap Variable list of string arguments.
535 */
536 __syscall void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source,
537 uint8_t level, const void *data,
538 size_t dlen, uint32_t package_flags,
539 const char *fmt,
540 va_list ap);
541
542 /** @brief Create message at runtime.
543 *
544 * Function allows to build any log message based on input data. Processing
545 * time is significantly higher than statically message creating.
546 *
547 * @param domain_id Domain ID.
548 *
549 * @param source Source.
550 *
551 * @param level Log level.
552 *
553 * @param data Data.
554 *
555 * @param dlen Data length.
556 *
557 * @param package_flags Package flags.
558 *
559 * @param fmt String.
560 *
561 * @param ... String arguments.
562 */
z_log_msg_runtime_create(uint8_t domain_id,const void * source,uint8_t level,const void * data,size_t dlen,uint32_t package_flags,const char * fmt,...)563 static inline void z_log_msg_runtime_create(uint8_t domain_id,
564 const void *source,
565 uint8_t level, const void *data,
566 size_t dlen, uint32_t package_flags,
567 const char *fmt, ...)
568 {
569 va_list ap;
570
571 va_start(ap, fmt);
572 z_log_msg_runtime_vcreate(domain_id, source, level,
573 data, dlen, package_flags, fmt, ap);
574 va_end(ap);
575 }
576
z_log_item_is_msg(const union log_msg_generic * msg)577 static inline bool z_log_item_is_msg(const union log_msg_generic *msg)
578 {
579 return msg->generic.type == Z_LOG_MSG_LOG;
580 }
581
582 /** @brief Get total length (in 32 bit words) of a log message.
583 *
584 * @param desc Log message descriptor.
585 *
586 * @return Length.
587 */
log_msg_get_total_wlen(const struct log_msg_desc desc)588 static inline uint32_t log_msg_get_total_wlen(const struct log_msg_desc desc)
589 {
590 return Z_LOG_MSG_ALIGNED_WLEN(desc.package_len, desc.data_len);
591 }
592
593 /** @brief Get length of the log item.
594 *
595 * @param item Item.
596 *
597 * @return Length in 32 bit words.
598 */
log_msg_generic_get_wlen(const union mpsc_pbuf_generic * item)599 static inline uint32_t log_msg_generic_get_wlen(const union mpsc_pbuf_generic *item)
600 {
601 const union log_msg_generic *generic_msg = (const union log_msg_generic *)item;
602
603 if (z_log_item_is_msg(generic_msg)) {
604 const struct log_msg *msg = (const struct log_msg *)generic_msg;
605
606 return log_msg_get_total_wlen(msg->hdr.desc);
607 }
608
609 return 0;
610 }
611
612 /** @brief Get log message domain ID.
613 *
614 * @param msg Log message.
615 *
616 * @return Domain ID
617 */
log_msg_get_domain(struct log_msg * msg)618 static inline uint8_t log_msg_get_domain(struct log_msg *msg)
619 {
620 return msg->hdr.desc.domain;
621 }
622
623 /** @brief Get log message level.
624 *
625 * @param msg Log message.
626 *
627 * @return Log level.
628 */
log_msg_get_level(struct log_msg * msg)629 static inline uint8_t log_msg_get_level(struct log_msg *msg)
630 {
631 return msg->hdr.desc.level;
632 }
633
634 /** @brief Get message source data.
635 *
636 * @param msg Log message.
637 *
638 * @return Pointer to the source data.
639 */
log_msg_get_source(struct log_msg * msg)640 static inline const void *log_msg_get_source(struct log_msg *msg)
641 {
642 return msg->hdr.source;
643 }
644
645 /** @brief Get timestamp.
646 *
647 * @param msg Log message.
648 *
649 * @return Timestamp.
650 */
log_msg_get_timestamp(struct log_msg * msg)651 static inline log_timestamp_t log_msg_get_timestamp(struct log_msg *msg)
652 {
653 return msg->hdr.timestamp;
654 }
655
656 /** @brief Get data buffer.
657 *
658 * @param msg log message.
659 *
660 * @param len location where data length is written.
661 *
662 * @return pointer to the data buffer.
663 */
log_msg_get_data(struct log_msg * msg,size_t * len)664 static inline uint8_t *log_msg_get_data(struct log_msg *msg, size_t *len)
665 {
666 *len = msg->hdr.desc.data_len;
667
668 return msg->data + msg->hdr.desc.package_len;
669 }
670
671 /** @brief Get string package.
672 *
673 * @param msg log message.
674 *
675 * @param len location where string package length is written.
676 *
677 * @return pointer to the package.
678 */
log_msg_get_package(struct log_msg * msg,size_t * len)679 static inline uint8_t *log_msg_get_package(struct log_msg *msg, size_t *len)
680 {
681 *len = msg->hdr.desc.package_len;
682
683 return msg->data;
684 }
685
686 /**
687 * @}
688 */
689
690 #include <syscalls/log_msg.h>
691
692 #ifdef __cplusplus
693 }
694 #endif
695
696 #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG_H_ */
697