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) && !defined(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 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 struct log_msg {
95 	struct log_msg_hdr hdr;
96 	/* Adding padding to ensure that cbprintf package that follows is
97 	 * properly aligned.
98 	 */
99 	uint8_t padding[Z_LOG_MSG_PADDING];
100 	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 struct log_msg_generic_hdr {
114 	LOG_MSG_GENERIC_HDR;
115 };
116 
117 union log_msg_generic {
118 	union mpsc_pbuf_generic buf;
119 	struct log_msg_generic_hdr generic;
120 	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 #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 #define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_0(fmt) 1
242 #define LOG_MSG_SIMPLE_ARG_TYPE_CHECK_1(fmt, arg) Z_CBPRINTF_IS_WORD_NUM(arg)
243 #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 #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 #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 #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  */
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,...)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 
z_log_item_is_msg(const union log_msg_generic * msg)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  */
log_msg_get_total_wlen(const struct log_msg_desc desc)730 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  */
log_msg_generic_get_wlen(const union mpsc_pbuf_generic * item)741 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  */
log_msg_get_domain(struct log_msg * msg)760 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  */
log_msg_get_level(struct log_msg * msg)771 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  */
log_msg_get_source(struct log_msg * msg)782 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 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  */
log_msg_get_timestamp(struct log_msg * msg)801 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  */
log_msg_get_tid(struct log_msg * msg)812 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  */
log_msg_get_data(struct log_msg * msg,size_t * len)830 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  */
log_msg_get_package(struct log_msg * msg,size_t * len)845 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_ */
863