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