Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2018 Nordic Semiconductor ASA
3 : : *
4 : : * SPDX-License-Identifier: Apache-2.0
5 : : */
6 : : #ifndef ZEPHYR_INCLUDE_LOGGING_LOG_CORE_H_
7 : : #define ZEPHYR_INCLUDE_LOGGING_LOG_CORE_H_
8 : :
9 : : #include <logging/log_msg.h>
10 : : #include <logging/log_msg2.h>
11 : : #include <logging/log_instance.h>
12 : : #include <stdbool.h>
13 : : #include <stdint.h>
14 : : #include <stdarg.h>
15 : : #include <syscall.h>
16 : : #include <sys/util.h>
17 : :
18 : : /* This header file keeps all macros and functions needed for creating logging
19 : : * messages (macros like @ref LOG_ERR).
20 : : */
21 : : #define LOG_LEVEL_NONE 0U
22 : : #define LOG_LEVEL_ERR 1U
23 : : #define LOG_LEVEL_WRN 2U
24 : : #define LOG_LEVEL_INF 3U
25 : : #define LOG_LEVEL_DBG 4U
26 : :
27 : : #ifdef __cplusplus
28 : : extern "C" {
29 : : #endif
30 : :
31 : : #ifndef CONFIG_LOG
32 : : #define CONFIG_LOG_DEFAULT_LEVEL 0U
33 : : #define CONFIG_LOG_MAX_LEVEL 0U
34 : : #endif
35 : :
36 : : #if !defined(CONFIG_LOG) || defined(CONFIG_LOG_MODE_MINIMAL)
37 : : #define CONFIG_LOG_DOMAIN_ID 0U
38 : : #endif
39 : :
40 : : #define LOG_FUNCTION_PREFIX_MASK \
41 : : (((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_ERR) << \
42 : : LOG_LEVEL_ERR) | \
43 : : ((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_WRN) << \
44 : : LOG_LEVEL_WRN) | \
45 : : ((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_INF) << \
46 : : LOG_LEVEL_INF) | \
47 : : ((uint32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_DBG) << LOG_LEVEL_DBG))
48 : :
49 : : /** @brief Macro for returning local level value if defined or default.
50 : : *
51 : : * Check @ref IS_ENABLED macro for detailed explanation of the trick.
52 : : */
53 : : #define Z_LOG_RESOLVED_LEVEL(_level, _default) \
54 : : Z_LOG_RESOLVED_LEVEL1(_level, _default)
55 : :
56 : : #define Z_LOG_RESOLVED_LEVEL1(_level, _default) \
57 : : __COND_CODE(_LOG_XXXX##_level, (_level), (_default))
58 : :
59 : : #define _LOG_XXXX0 _LOG_YYYY,
60 : : #define _LOG_XXXX0U _LOG_YYYY,
61 : : #define _LOG_XXXX1 _LOG_YYYY,
62 : : #define _LOG_XXXX1U _LOG_YYYY,
63 : : #define _LOG_XXXX2 _LOG_YYYY,
64 : : #define _LOG_XXXX2U _LOG_YYYY,
65 : : #define _LOG_XXXX3 _LOG_YYYY,
66 : : #define _LOG_XXXX3U _LOG_YYYY,
67 : : #define _LOG_XXXX4 _LOG_YYYY,
68 : : #define _LOG_XXXX4U _LOG_YYYY,
69 : :
70 : : /**
71 : : * @brief Macro for conditional code generation if provided log level allows.
72 : : *
73 : : * Macro behaves similarly to standard \#if \#else \#endif clause. The
74 : : * difference is that it is evaluated when used and not when header file is
75 : : * included.
76 : : *
77 : : * @param _eval_level Evaluated level. If level evaluates to one of existing log
78 : : * log level (1-4) then macro evaluates to _iftrue.
79 : : * @param _iftrue Code that should be inserted when evaluated to true. Note,
80 : : * that parameter must be provided in brackets.
81 : : * @param _iffalse Code that should be inserted when evaluated to false.
82 : : * Note, that parameter must be provided in brackets.
83 : : */
84 : : #define Z_LOG_EVAL(_eval_level, _iftrue, _iffalse) \
85 : : Z_LOG_EVAL1(_eval_level, _iftrue, _iffalse)
86 : :
87 : : #define Z_LOG_EVAL1(_eval_level, _iftrue, _iffalse) \
88 : : __COND_CODE(_LOG_ZZZZ##_eval_level, _iftrue, _iffalse)
89 : :
90 : : #define _LOG_ZZZZ1 _LOG_YYYY,
91 : : #define _LOG_ZZZZ1U _LOG_YYYY,
92 : : #define _LOG_ZZZZ2 _LOG_YYYY,
93 : : #define _LOG_ZZZZ2U _LOG_YYYY,
94 : : #define _LOG_ZZZZ3 _LOG_YYYY,
95 : : #define _LOG_ZZZZ3U _LOG_YYYY,
96 : : #define _LOG_ZZZZ4 _LOG_YYYY,
97 : : #define _LOG_ZZZZ4U _LOG_YYYY,
98 : :
99 : : /** @brief Macro for getting log level for given module.
100 : : *
101 : : * It is evaluated to LOG_LEVEL if defined. Otherwise CONFIG_LOG_DEFAULT_LEVEL
102 : : * is used.
103 : : */
104 : : #define _LOG_LEVEL() Z_LOG_RESOLVED_LEVEL(LOG_LEVEL, CONFIG_LOG_DEFAULT_LEVEL)
105 : :
106 : : /**
107 : : * @def LOG_CONST_ID_GET
108 : : * @brief Macro for getting ID of the element of the section.
109 : : *
110 : : * @param _addr Address of the element.
111 : : */
112 : : #define LOG_CONST_ID_GET(_addr) \
113 : : COND_CODE_1(CONFIG_LOG, ((__log_level ? log_const_source_id(_addr) : 0)), (0))
114 : :
115 : : /**
116 : : * @def LOG_CURRENT_MODULE_ID
117 : : * @brief Macro for getting ID of current module.
118 : : */
119 : : #define LOG_CURRENT_MODULE_ID() (__log_level != 0 ? \
120 : : log_const_source_id(__log_current_const_data) : 0U)
121 : :
122 : : /**
123 : : * @def LOG_CURRENT_DYNAMIC_DATA_ADDR
124 : : * @brief Macro for getting address of dynamic structure of current module.
125 : : */
126 : : #define LOG_CURRENT_DYNAMIC_DATA_ADDR() (__log_level ? \
127 : : __log_current_dynamic_data : (struct log_source_dynamic_data *)0U)
128 : :
129 : : /** @brief Macro for getting ID of the element of the section.
130 : : *
131 : : * @param _addr Address of the element.
132 : : */
133 : : #define LOG_DYNAMIC_ID_GET(_addr) \
134 : : COND_CODE_1(CONFIG_LOG, ((__log_level ? log_dynamic_source_id(_addr) : 0)), (0))
135 : :
136 : : /* Set of defines that are set to 1 if function name prefix is enabled for given level. */
137 : : #define Z_LOG_FUNC_PREFIX_0U 0
138 : : #define Z_LOG_FUNC_PREFIX_1U COND_CODE_1(CONFIG_LOG_FUNC_NAME_PREFIX_ERR, (1), (0))
139 : : #define Z_LOG_FUNC_PREFIX_2U COND_CODE_1(CONFIG_LOG_FUNC_NAME_PREFIX_WRN, (1), (0))
140 : : #define Z_LOG_FUNC_PREFIX_3U COND_CODE_1(CONFIG_LOG_FUNC_NAME_PREFIX_INF, (1), (0))
141 : : #define Z_LOG_FUNC_PREFIX_4U COND_CODE_1(CONFIG_LOG_FUNC_NAME_PREFIX_DBG, (1), (0))
142 : :
143 : : /**
144 : : * @brief Macro for optional injection of function name as first argument of
145 : : * formatted string. COND_CODE_0() macro is used to handle no arguments
146 : : * case.
147 : : *
148 : : * The purpose of this macro is to prefix string literal with format specifier
149 : : * for function name and inject function name as first argument. In order to
150 : : * handle string with no arguments _LOG_Z_EVAL is used.
151 : : */
152 : : #define Z_LOG_STR_WITH_PREFIX2(...) \
153 : : "%s: " GET_ARG_N(1, __VA_ARGS__), (const char *)__func__\
154 : : COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__),\
155 : : (),\
156 : : (, GET_ARGS_LESS_N(1, __VA_ARGS__))\
157 : : )
158 : :
159 : : /* Macro handles case when no format string is provided: e.g. LOG_DBG().
160 : : * Handling of format string is deferred to the next level macro.
161 : : */
162 : : #define Z_LOG_STR_WITH_PREFIX(...) \
163 : : COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
164 : : ("%s", (const char *)__func__), \
165 : : (Z_LOG_STR_WITH_PREFIX2(__VA_ARGS__)))
166 : :
167 : : /**
168 : : * @brief Handle optional injection of function name as the first argument.
169 : : *
170 : : * Additionally, macro is handling the empty message case.
171 : : */
172 : : #define Z_LOG_STR(_level, ...) \
173 : : COND_CODE_1(UTIL_CAT(Z_LOG_FUNC_PREFIX_##_level), \
174 : : (Z_LOG_STR_WITH_PREFIX(__VA_ARGS__)), (__VA_ARGS__))
175 : :
176 : : /******************************************************************************/
177 : : /****************** Internal macros for log frontend **************************/
178 : : /******************************************************************************/
179 : : /**@brief Second stage for Z_LOG_NARGS_POSTFIX */
180 : : #define Z_LOG_NARGS_POSTFIX_IMPL( \
181 : : _ignored, \
182 : : _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
183 : : _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, \
184 : : _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, N, ...) N
185 : :
186 : : /**@brief Macro to get the postfix for further log message processing.
187 : : *
188 : : * Logs with more than 3 arguments are processed in a generic way.
189 : : *
190 : : * param[in] ... List of arguments
191 : : *
192 : : * @retval Postfix, number of arguments or _LONG when more than 3 arguments.
193 : : */
194 : : #define Z_LOG_NARGS_POSTFIX(...) \
195 : : Z_LOG_NARGS_POSTFIX_IMPL(__VA_ARGS__, LONG, LONG, LONG, LONG, LONG, \
196 : : LONG, LONG, LONG, LONG, LONG, LONG, LONG, LONG, LONG, \
197 : : LONG, LONG, LONG, LONG, LONG, LONG, LONG, LONG, LONG, \
198 : : LONG, LONG, LONG, LONG, LONG, LONG, 3, 2, 1, 0, ~)
199 : :
200 : : #define Z_LOG_INTERNAL_X(N, ...) UTIL_CAT(_LOG_INTERNAL_, N)(__VA_ARGS__)
201 : :
202 : : #define Z_LOG_INTERNAL2(is_user_context, _src_level, ...) do { \
203 : : if (is_user_context) { \
204 : : if (!IS_ENABLED(CONFIG_LOG_FRONTEND)) { \
205 : : log_from_user(_src_level, __VA_ARGS__); \
206 : : } \
207 : : } else if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) { \
208 : : log_string_sync(_src_level, __VA_ARGS__); \
209 : : } else { \
210 : : Z_LOG_INTERNAL_X(Z_LOG_NARGS_POSTFIX(__VA_ARGS__), \
211 : : _src_level, __VA_ARGS__); \
212 : : } \
213 : : } while (false)
214 : :
215 : : #define Z_LOG_INTERNAL(is_user_context, _level, _source, _dsource, ...) do { \
216 : : uint16_t src_id = \
217 : : IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
218 : : LOG_DYNAMIC_ID_GET(_dsource) : LOG_CONST_ID_GET(_source); \
219 : : struct log_msg_ids src_level = { \
220 : : .level = _level, \
221 : : .domain_id = CONFIG_LOG_DOMAIN_ID, \
222 : : .source_id = src_id \
223 : : }; \
224 : : Z_LOG_INTERNAL2(is_user_context, src_level, \
225 : : Z_LOG_STR(_level, __VA_ARGS__)); \
226 : : } while (0)
227 : :
228 : : #define _LOG_INTERNAL_0(_src_level, _str) \
229 : : log_0(_str, _src_level)
230 : :
231 : : #define _LOG_INTERNAL_1(_src_level, _str, _arg0) \
232 : : log_1(_str, (log_arg_t)(_arg0), _src_level)
233 : :
234 : : #define _LOG_INTERNAL_2(_src_level, _str, _arg0, _arg1) \
235 : : log_2(_str, (log_arg_t)(_arg0), (log_arg_t)(_arg1), _src_level)
236 : :
237 : : #define _LOG_INTERNAL_3(_src_level, _str, _arg0, _arg1, _arg2) \
238 : : log_3(_str, (log_arg_t)(_arg0), (log_arg_t)(_arg1), (log_arg_t)(_arg2), _src_level)
239 : :
240 : : #define __LOG_ARG_CAST(_x) (log_arg_t)(_x)
241 : :
242 : : #define __LOG_ARGUMENTS(...) FOR_EACH(__LOG_ARG_CAST, (,), __VA_ARGS__)
243 : :
244 : : #define _LOG_INTERNAL_LONG(_src_level, _str, ...) \
245 : : do { \
246 : : log_arg_t args[] = {__LOG_ARGUMENTS(__VA_ARGS__)};\
247 : : log_n(_str, args, ARRAY_SIZE(args), _src_level); \
248 : : } while (false)
249 : :
250 : : #define Z_LOG_LEVEL_CHECK(_level, _check_level, _default_level) \
251 : : (_level <= Z_LOG_RESOLVED_LEVEL(_check_level, _default_level))
252 : :
253 : : #define Z_LOG_CONST_LEVEL_CHECK(_level) \
254 : : (IS_ENABLED(CONFIG_LOG) && \
255 : : (Z_LOG_LEVEL_CHECK(_level, CONFIG_LOG_OVERRIDE_LEVEL, LOG_LEVEL_NONE) \
256 : : || \
257 : : ((IS_ENABLED(CONFIG_LOG_OVERRIDE_LEVEL) == false) && \
258 : : (_level <= __log_level) && \
259 : : (_level <= CONFIG_LOG_MAX_LEVEL) \
260 : : ) \
261 : : ))
262 : :
263 : : /*****************************************************************************/
264 : : /****************** Definitions used by minimal logging *********************/
265 : : /*****************************************************************************/
266 : : void z_log_minimal_hexdump_print(int level, const void *data, size_t size);
267 : : void z_log_minimal_vprintk(const char *fmt, va_list ap);
268 : : void z_log_minimal_printk(const char *fmt, ...);
269 : :
270 : : #define Z_LOG_TO_PRINTK(_level, fmt, ...) do { \
271 : : z_log_minimal_printk("%c: " fmt "\n", \
272 : : z_log_minimal_level_to_char(_level), \
273 : : ##__VA_ARGS__); \
274 : : } while (false)
275 : :
276 : : #define Z_LOG_TO_VPRINTK(_level, fmt, valist) do { \
277 : : z_log_minimal_printk("%c: ", z_log_minimal_level_to_char(_level)); \
278 : : z_log_minimal_vprintk(fmt, valist); \
279 : : z_log_minimal_printk("\n"); \
280 : : } while (false)
281 : :
282 : 0 : static inline char z_log_minimal_level_to_char(int level)
283 : : {
284 [ # # # # : 0 : switch (level) {
# ]
285 : 0 : case LOG_LEVEL_ERR:
286 : 0 : return 'E';
287 : 0 : case LOG_LEVEL_WRN:
288 : 0 : return 'W';
289 : 0 : case LOG_LEVEL_INF:
290 : 0 : return 'I';
291 : 0 : case LOG_LEVEL_DBG:
292 : 0 : return 'D';
293 : 0 : default:
294 : 0 : return '?';
295 : : }
296 : : }
297 : :
298 : : #define Z_LOG_INST(_inst) COND_CODE_1(CONFIG_LOG, (_inst), NULL)
299 : :
300 : : /*****************************************************************************/
301 : : /****************** Macros for standard logging ******************************/
302 : : /*****************************************************************************/
303 : : /** @internal
304 : : * @brief Generic logging macro.
305 : : *
306 : : * It checks against static levels (resolved at compile timer), runtime levels
307 : : * and modes and dispatch to relevant processing path.
308 : : *
309 : : * @param _level Log message severity level.
310 : : *
311 : : * @param _inst Set to 1 for instance specific log message. 0 otherwise.
312 : : *
313 : : * @param _source Pointer to static source descriptor object. NULL when runtime filtering
314 : : * is enabled.
315 : : *
316 : : * @param _dsource Pointer to dynamic source descriptor. NULL when runtime filtering
317 : : * is disabled.
318 : : *
319 : : * @param ... String with arguments.
320 : : */
321 : : #define Z_LOG2(_level, _inst, _source, _dsource, ...) do { \
322 : : if (!Z_LOG_CONST_LEVEL_CHECK(_level)) { \
323 : : break; \
324 : : } \
325 : : if (IS_ENABLED(CONFIG_LOG_MODE_MINIMAL)) { \
326 : : Z_LOG_TO_PRINTK(_level, __VA_ARGS__); \
327 : : break; \
328 : : } \
329 : : /* For instance logging check instance specific static level */ \
330 : : if (_inst & !IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) { \
331 : : if (_level > ((struct log_source_const_data *)_source)->level) { \
332 : : break; \
333 : : } \
334 : : } \
335 : : \
336 : : bool is_user_context = k_is_user_context(); \
337 : : uint32_t filters = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
338 : : (_dsource)->filters : 0;\
339 : : if (!IS_ENABLED(CONFIG_LOG_FRONTEND) && IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && \
340 : : !is_user_context && _level > Z_LOG_RUNTIME_FILTER(filters)) { \
341 : : break; \
342 : : } \
343 : : if (IS_ENABLED(CONFIG_LOG2)) { \
344 : : int _mode; \
345 : : void *_src = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
346 : : (void *)_dsource : (void *)_source; \
347 : : Z_LOG_MSG2_CREATE(UTIL_NOT(IS_ENABLED(CONFIG_USERSPACE)), _mode, \
348 : : CONFIG_LOG_DOMAIN_ID, _src, _level, NULL,\
349 : : 0, __VA_ARGS__); \
350 : : } else { \
351 : : Z_LOG_INTERNAL(is_user_context, _level, \
352 : : _source, _dsource, __VA_ARGS__);\
353 : : } \
354 : : if (false) { \
355 : : /* Arguments checker present but never evaluated.*/ \
356 : : /* Placed here to ensure that __VA_ARGS__ are*/ \
357 : : /* evaluated once when log is enabled.*/ \
358 : : z_log_printf_arg_checker(__VA_ARGS__); \
359 : : } \
360 : : } while (false)
361 : :
362 : : #define Z_LOG(_level, ...) \
363 : : Z_LOG2(_level, 0, __log_current_const_data, __log_current_dynamic_data, __VA_ARGS__)
364 : :
365 : : #define Z_LOG_INSTANCE(_level, _inst, ...) \
366 : : Z_LOG2(_level, 1, \
367 : : COND_CODE_1(CONFIG_LOG_RUNTIME_FILTERING, (NULL), (Z_LOG_INST(_inst))), \
368 : : (struct log_source_dynamic_data *)COND_CODE_1( \
369 : : CONFIG_LOG_RUNTIME_FILTERING, \
370 : : (Z_LOG_INST(_inst)), (NULL)), \
371 : : __VA_ARGS__)
372 : :
373 : : /*****************************************************************************/
374 : : /****************** Macros for hexdump logging *******************************/
375 : : /*****************************************************************************/
376 : : /** @internal
377 : : * @brief Generic logging macro.
378 : : *
379 : : * It checks against static levels (resolved at compile timer), runtime levels
380 : : * and modes and dispatch to relevant processing path.
381 : : *
382 : : * @param _level Log message severity level.
383 : : *
384 : : * @param _inst Set to 1 for instance specific log message. 0 otherwise.
385 : : *
386 : : * @param _source Pointer to static source descriptor object. NULL when runtime filtering
387 : : * is enabled.
388 : : *
389 : : * @param _dsource Pointer to dynamic source descriptor. NULL when runtime filtering
390 : : * is disabled.
391 : : *
392 : : * @param _data Hexdump data;
393 : : *
394 : : * @param _len Hexdump data length.
395 : : *
396 : : * @param ... String.
397 : : */
398 : : #define Z_LOG_HEXDUMP2(_level, _inst, _source, _dsource, _data, _len, ...) do { \
399 : : const char *_str = GET_ARG_N(1, __VA_ARGS__); \
400 : : if (!Z_LOG_CONST_LEVEL_CHECK(_level)) { \
401 : : break; \
402 : : } \
403 : : /* For instance logging check instance specific static level */ \
404 : : if (_inst & !IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) { \
405 : : if (_level > ((struct log_source_const_data *)_source)->level) { \
406 : : break; \
407 : : } \
408 : : } \
409 : : bool is_user_context = k_is_user_context(); \
410 : : uint32_t filters = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
411 : : (_dsource)->filters : 0;\
412 : : \
413 : : if (IS_ENABLED(CONFIG_LOG_MODE_MINIMAL)) { \
414 : : Z_LOG_TO_PRINTK(_level, "%s", _str); \
415 : : z_log_minimal_hexdump_print(_level, \
416 : : (const char *)_data, _len);\
417 : : break; \
418 : : } \
419 : : if (!IS_ENABLED(CONFIG_LOG_FRONTEND) && IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && \
420 : : !is_user_context && _level > Z_LOG_RUNTIME_FILTER(filters)) { \
421 : : break; \
422 : : } \
423 : : if (IS_ENABLED(CONFIG_LOG2)) { \
424 : : int mode; \
425 : : void *_src = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
426 : : (void *)_dsource : (void *)_source; \
427 : : Z_LOG_MSG2_CREATE(UTIL_NOT(IS_ENABLED(CONFIG_USERSPACE)), mode, \
428 : : CONFIG_LOG_DOMAIN_ID, _src, _level, \
429 : : _data, _len, \
430 : : COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
431 : : (), \
432 : : (COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
433 : : ("%s", __VA_ARGS__), (__VA_ARGS__)))));\
434 : : break; \
435 : : } \
436 : : uint16_t src_id = \
437 : : IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
438 : : LOG_DYNAMIC_ID_GET(_dsource) : LOG_CONST_ID_GET(_source);\
439 : : struct log_msg_ids src_level = { \
440 : : .level = _level, \
441 : : .domain_id = CONFIG_LOG_DOMAIN_ID, \
442 : : .source_id = src_id, \
443 : : }; \
444 : : if (is_user_context) { \
445 : : if (!IS_ENABLED(CONFIG_LOG_FRONTEND)) { \
446 : : log_hexdump_from_user(src_level, _str, (const char *)_data, _len); \
447 : : } \
448 : : } else if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) { \
449 : : log_hexdump_sync(src_level, _str, (const char *)_data, _len); \
450 : : } else { \
451 : : log_hexdump(_str, (const char *)_data, _len, src_level); \
452 : : } \
453 : : } while (false)
454 : :
455 : : #define Z_LOG_HEXDUMP(_level, _data, _length, ...) \
456 : : Z_LOG_HEXDUMP2(_level, 0, \
457 : : __log_current_const_data, \
458 : : __log_current_dynamic_data, \
459 : : _data, _length, __VA_ARGS__)
460 : :
461 : : #define Z_LOG_HEXDUMP_INSTANCE(_level, _inst, _data, _length, _str) \
462 : : Z_LOG_HEXDUMP2(_level, 1, \
463 : : COND_CODE_1(CONFIG_LOG_RUNTIME_FILTERING, (NULL), (Z_LOG_INST(_inst))), \
464 : : (struct log_source_dynamic_data *)COND_CODE_1( \
465 : : CONFIG_LOG_RUNTIME_FILTERING, \
466 : : (Z_LOG_INST(_inst)), (NULL)), \
467 : : _data, _length, _str)
468 : :
469 : : /*****************************************************************************/
470 : : /****************** Filtering macros *****************************************/
471 : : /*****************************************************************************/
472 : :
473 : : /** @brief Number of bits used to encode log level. */
474 : : #define LOG_LEVEL_BITS 3U
475 : :
476 : : /** @brief Filter slot size. */
477 : : #define LOG_FILTER_SLOT_SIZE LOG_LEVEL_BITS
478 : :
479 : : /** @brief Number of slots in one word. */
480 : : #define LOG_FILTERS_NUM_OF_SLOTS (32 / LOG_FILTER_SLOT_SIZE)
481 : :
482 : : /** @brief Slot mask. */
483 : : #define LOG_FILTER_SLOT_MASK (BIT(LOG_FILTER_SLOT_SIZE) - 1U)
484 : :
485 : : /** @brief Bit offset of a slot.
486 : : *
487 : : * @param _id Slot ID.
488 : : */
489 : : #define LOG_FILTER_SLOT_SHIFT(_id) (LOG_FILTER_SLOT_SIZE * (_id))
490 : :
491 : : #define LOG_FILTER_SLOT_GET(_filters, _id) \
492 : : ((*(_filters) >> LOG_FILTER_SLOT_SHIFT(_id)) & LOG_FILTER_SLOT_MASK)
493 : :
494 : : #define LOG_FILTER_SLOT_SET(_filters, _id, _filter) \
495 : : do { \
496 : : *(_filters) &= ~(LOG_FILTER_SLOT_MASK << \
497 : : LOG_FILTER_SLOT_SHIFT(_id)); \
498 : : *(_filters) |= ((_filter) & LOG_FILTER_SLOT_MASK) << \
499 : : LOG_FILTER_SLOT_SHIFT(_id); \
500 : : } while (false)
501 : :
502 : : #define LOG_FILTER_AGGR_SLOT_IDX 0
503 : :
504 : : #define LOG_FILTER_AGGR_SLOT_GET(_filters) \
505 : : LOG_FILTER_SLOT_GET(_filters, LOG_FILTER_AGGR_SLOT_IDX)
506 : :
507 : : #define LOG_FILTER_FIRST_BACKEND_SLOT_IDX 1
508 : :
509 : : /* Return aggregated (highest) level for all enabled backends, e.g. if there
510 : : * are 3 active backends, one backend is set to get INF logs from a module and
511 : : * two other backends are set for ERR, returned level is INF.
512 : : */
513 : : #define Z_LOG_RUNTIME_FILTER(_filter) \
514 : : LOG_FILTER_SLOT_GET(&_filter, LOG_FILTER_AGGR_SLOT_IDX)
515 : :
516 : : /** @brief Log level value used to indicate log entry that should not be
517 : : * formatted (raw string).
518 : : */
519 : : #define LOG_LEVEL_INTERNAL_RAW_STRING LOG_LEVEL_NONE
520 : :
521 : : extern struct log_source_const_data __log_const_start[];
522 : : extern struct log_source_const_data __log_const_end[];
523 : :
524 : : /** @brief Enum with possible actions for strdup operation. */
525 : : enum log_strdup_action {
526 : : LOG_STRDUP_SKIP, /**< None RAM string duplication. */
527 : : LOG_STRDUP_EXEC, /**< Always duplicate RAM strings. */
528 : : LOG_STRDUP_CHECK_EXEC/**< Duplicate RAM strings, if not dupl. before.*/
529 : : };
530 : :
531 : : #define Z_LOG_PRINTK(...) do { \
532 : : if (IS_ENABLED(CONFIG_LOG_MODE_MINIMAL) || !IS_ENABLED(CONFIG_LOG2)) { \
533 : : z_log_minimal_printk(__VA_ARGS__); \
534 : : break; \
535 : : } \
536 : : int _mode; \
537 : : if (0) {\
538 : : z_log_printf_arg_checker(__VA_ARGS__); \
539 : : } \
540 : : Z_LOG_MSG2_CREATE(!IS_ENABLED(CONFIG_USERSPACE), _mode, \
541 : : CONFIG_LOG_DOMAIN_ID, NULL, \
542 : : LOG_LEVEL_INTERNAL_RAW_STRING, NULL, 0, __VA_ARGS__);\
543 : : } while (0)
544 : :
545 : : /** @brief Get index of the log source based on the address of the constant data
546 : : * associated with the source.
547 : : *
548 : : * @param data Address of the constant data.
549 : : *
550 : : * @return Source ID.
551 : : */
552 : : static inline uint32_t log_const_source_id(
553 : : const struct log_source_const_data *data)
554 : : {
555 : : return ((const uint8_t *)data - (uint8_t *)__log_const_start)/
556 : : sizeof(struct log_source_const_data);
557 : : }
558 : :
559 : : extern struct log_source_dynamic_data __log_dynamic_start[];
560 : : extern struct log_source_dynamic_data __log_dynamic_end[];
561 : :
562 : : /** @brief Creates name of variable and section for runtime log data.
563 : : *
564 : : * @param _name Name.
565 : : */
566 : : #define LOG_ITEM_DYNAMIC_DATA(_name) UTIL_CAT(log_dynamic_, _name)
567 : :
568 : : #define LOG_INSTANCE_DYNAMIC_DATA(_module_name, _inst) \
569 : : LOG_ITEM_DYNAMIC_DATA(Z_LOG_INSTANCE_FULL_NAME(_module_name, _inst))
570 : :
571 : : /** @brief Get index of the log source based on the address of the dynamic data
572 : : * associated with the source.
573 : : *
574 : : * @param data Address of the dynamic data.
575 : : *
576 : : * @return Source ID.
577 : : */
578 : : static inline uint32_t log_dynamic_source_id(struct log_source_dynamic_data *data)
579 : : {
580 : : return ((uint8_t *)data - (uint8_t *)__log_dynamic_start)/
581 : : sizeof(struct log_source_dynamic_data);
582 : : }
583 : :
584 : : /** @brief Dummy function to trigger log messages arguments type checking. */
585 : : static inline __printf_like(1, 2)
586 : : void z_log_printf_arg_checker(const char *fmt, ...)
587 : : {
588 : : ARG_UNUSED(fmt);
589 : : }
590 : :
591 : : /** @brief Standard log with no arguments.
592 : : *
593 : : * @param str String.
594 : : * @param src_level Log identification.
595 : : */
596 : : void log_0(const char *str, struct log_msg_ids src_level);
597 : :
598 : : /** @brief Standard log with one argument.
599 : : *
600 : : * @param str String.
601 : : * @param arg1 First argument.
602 : : * @param src_level Log identification.
603 : : */
604 : : void log_1(const char *str,
605 : : log_arg_t arg1,
606 : : struct log_msg_ids src_level);
607 : :
608 : : /** @brief Standard log with two arguments.
609 : : *
610 : : * @param str String.
611 : : * @param arg1 First argument.
612 : : * @param arg2 Second argument.
613 : : * @param src_level Log identification.
614 : : */
615 : : void log_2(const char *str,
616 : : log_arg_t arg1,
617 : : log_arg_t arg2,
618 : : struct log_msg_ids src_level);
619 : :
620 : : /** @brief Standard log with three arguments.
621 : : *
622 : : * @param str String.
623 : : * @param arg1 First argument.
624 : : * @param arg2 Second argument.
625 : : * @param arg3 Third argument.
626 : : * @param src_level Log identification.
627 : : */
628 : : void log_3(const char *str,
629 : : log_arg_t arg1,
630 : : log_arg_t arg2,
631 : : log_arg_t arg3,
632 : : struct log_msg_ids src_level);
633 : :
634 : : /** @brief Standard log with arguments list.
635 : : *
636 : : * @param str String.
637 : : * @param args Array with arguments.
638 : : * @param narg Number of arguments in the array.
639 : : * @param src_level Log identification.
640 : : */
641 : : void log_n(const char *str,
642 : : log_arg_t *args,
643 : : uint32_t narg,
644 : : struct log_msg_ids src_level);
645 : :
646 : : /** @brief Hexdump log.
647 : : *
648 : : * @param str String.
649 : : * @param data Data.
650 : : * @param length Data length.
651 : : * @param src_level Log identification.
652 : : */
653 : : void log_hexdump(const char *str, const void *data, uint32_t length,
654 : : struct log_msg_ids src_level);
655 : :
656 : : /** @brief Process log message synchronously.
657 : : *
658 : : * @param src_level Log message details.
659 : : * @param fmt String to format.
660 : : * @param ... Variable list of arguments.
661 : : */
662 : : void log_string_sync(struct log_msg_ids src_level, const char *fmt, ...);
663 : :
664 : : /** @brief Process log hexdump message synchronously.
665 : : *
666 : : * @param src_level Log message details.
667 : : * @param metadata Raw string associated with the data.
668 : : * @param data Data.
669 : : * @param len Data length.
670 : : */
671 : : void log_hexdump_sync(struct log_msg_ids src_level, const char *metadata,
672 : : const void *data, uint32_t len);
673 : :
674 : : /**
675 : : * @brief Writes a generic log message to the log.
676 : : *
677 : : * @note This function is intended to be used when porting other log systems.
678 : : *
679 : : * @param src_level Log identification.
680 : : * @param fmt String to format.
681 : : * @param ap Pointer to arguments list.
682 : : * @param strdup_action Manages strdup activity.
683 : : */
684 : : void log_generic(struct log_msg_ids src_level, const char *fmt, va_list ap,
685 : : enum log_strdup_action strdup_action);
686 : :
687 : : /**
688 : : * @brief Writes a generic log message to the logging v2.
689 : : *
690 : : * @note This function is intended to be used when porting other log systems.
691 : : *
692 : : * @param level Log level..
693 : : * @param fmt String to format.
694 : : * @param ap Pointer to arguments list.
695 : : */
696 : : static inline void log2_generic(uint8_t level, const char *fmt, va_list ap)
697 : : {
698 : : z_log_msg2_runtime_vcreate(CONFIG_LOG_DOMAIN_ID, NULL, level,
699 : : NULL, 0, 0, fmt, ap);
700 : : }
701 : :
702 : : /**
703 : : * @brief Returns number of arguments visible from format string.
704 : : *
705 : : * @note This function is intended to be used when porting other log systems.
706 : : *
707 : : * @param fmt Format string.
708 : : *
709 : : * @return Number of arguments.
710 : : */
711 : : uint32_t log_count_args(const char *fmt);
712 : :
713 : : /**
714 : : * @brief Writes a generic log message to the log from user mode.
715 : : *
716 : : * @note This function is intended to be used internally
717 : : * by the logging subsystem.
718 : : */
719 : : void log_generic_from_user(struct log_msg_ids src_level,
720 : : const char *fmt, va_list ap);
721 : :
722 : : /** @brief Check if address belongs to the memory pool used for transient.
723 : : *
724 : : * @param buf Buffer.
725 : : *
726 : : * @return True if address within the pool, false otherwise.
727 : : */
728 : : bool log_is_strdup(const void *buf);
729 : :
730 : : /** @brief Log a message from user mode context.
731 : : *
732 : : * @note This function is intended to be used internally
733 : : * by the logging subsystem.
734 : : *
735 : : * @param src_level Log identification.
736 : : * @param fmt String to format.
737 : : * @param ... Variable list of arguments.
738 : : */
739 : : void __printf_like(2, 3) log_from_user(struct log_msg_ids src_level,
740 : : const char *fmt, ...);
741 : :
742 : : /* Internal function used by log_from_user(). */
743 : : __syscall void z_log_string_from_user(uint32_t src_level_val, const char *str);
744 : :
745 : : /**
746 : : * @brief Create mask with occurrences of a string format specifiers (%s).
747 : : *
748 : : * Result is stored as the mask (argument n is n'th bit). Bit is set if string
749 : : * format specifier was found.
750 : : *
751 : : * @param str String.
752 : : * @param nargs Number of arguments in the string.
753 : : *
754 : : * @return Mask with %s format specifiers found.
755 : : */
756 : : uint32_t z_log_get_s_mask(const char *str, uint32_t nargs);
757 : :
758 : : /** @brief Log binary data (displayed as hexdump) from user mode context.
759 : : *
760 : : * @note This function is intended to be used internally
761 : : * by the logging subsystem.
762 : : *
763 : : * @param src_level Log identification.
764 : : * @param metadata Raw string associated with the data.
765 : : * @param data Data.
766 : : * @param len Data length.
767 : : */
768 : : void log_hexdump_from_user(struct log_msg_ids src_level, const char *metadata,
769 : : const void *data, uint32_t len);
770 : :
771 : : /* Internal function used by log_hexdump_from_user(). */
772 : : __syscall void z_log_hexdump_from_user(uint32_t src_level_val,
773 : : const char *metadata,
774 : : const uint8_t *data, uint32_t len);
775 : :
776 : : /******************************************************************************/
777 : : /********** Macros _VA operate on var-args parameters. ***************/
778 : : /********* Intended to be used when porting other log systems. ***************/
779 : : /********* Shall be used in the log entry interface function. ***************/
780 : : /********* Speed optimized for up to three arguments number. ***************/
781 : : /******************************************************************************/
782 : : #define Z_LOG_VA(_level, _str, _valist, _argnum, _strdup_action)\
783 : : __LOG_VA(_level, \
784 : : __log_current_const_data, \
785 : : __log_current_dynamic_data, \
786 : : _str, _valist, _argnum, _strdup_action)
787 : :
788 : : #define __LOG_VA(_level, _source, _dsource, _str, _valist, _argnum, _strdup_action) do { \
789 : : if (!Z_LOG_CONST_LEVEL_CHECK(_level)) { \
790 : : break; \
791 : : } \
792 : : if (IS_ENABLED(CONFIG_LOG_MODE_MINIMAL)) { \
793 : : Z_LOG_TO_VPRINTK(_level, _str, _valist); \
794 : : break; \
795 : : } \
796 : : \
797 : : bool is_user_context = k_is_user_context(); \
798 : : uint32_t filters = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
799 : : _dsource->filters : 0;\
800 : : if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && !is_user_context && \
801 : : _level > Z_LOG_RUNTIME_FILTER(filters)) { \
802 : : break; \
803 : : } \
804 : : if (IS_ENABLED(CONFIG_LOG2)) { \
805 : : void *_src = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
806 : : (void *)_dsource : (void *)_source; \
807 : : z_log_msg2_runtime_vcreate(CONFIG_LOG_DOMAIN_ID, _src, \
808 : : _level, NULL, 0, 0, _str, _valist); \
809 : : break; \
810 : : } \
811 : : uint16_t _id = \
812 : : IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
813 : : LOG_DYNAMIC_ID_GET(_dsource) : LOG_CONST_ID_GET(_source);\
814 : : struct log_msg_ids src_level = { \
815 : : .level = _level, \
816 : : .domain_id = CONFIG_LOG_DOMAIN_ID, \
817 : : .source_id = _id \
818 : : }; \
819 : : __LOG_INTERNAL_VA(is_user_context, \
820 : : src_level, \
821 : : _str, _valist, _argnum, \
822 : : _strdup_action); \
823 : : } while (false)
824 : :
825 : : /**
826 : : * @brief Inline function to perform strdup, used in __LOG_INTERNAL_VA macro
827 : : *
828 : : * @note This function is intended to be used when porting other log systems.
829 : : *
830 : : * @param msk Bitmask marking all %s arguments.
831 : : * @param idx Index of actually processed argument.
832 : : * @param param Value of actually processed argument.
833 : : * @param action Action for strdup operation.
834 : : *
835 : : * @return Duplicated string or not changed param.
836 : : */
837 : : static inline log_arg_t z_log_do_strdup(uint32_t msk, uint32_t idx,
838 : : log_arg_t param,
839 : : enum log_strdup_action action)
840 : : {
841 : : #ifndef CONFIG_LOG_MODE_MINIMAL
842 : : char *z_log_strdup(const char *str);
843 : :
844 : : if (msk & (1 << idx)) {
845 : : const char *str = (const char *)param;
846 : : /* is_rodata(str) is not checked,
847 : : * because log_strdup does it.
848 : : * Hence, we will do only optional check
849 : : * if already not duplicated.
850 : : */
851 : : if (action == LOG_STRDUP_EXEC || !log_is_strdup(str)) {
852 : : param = (log_arg_t)z_log_strdup(str);
853 : : }
854 : : }
855 : : #else
856 : : ARG_UNUSED(msk);
857 : : ARG_UNUSED(idx);
858 : : ARG_UNUSED(action);
859 : : #endif
860 : : return param;
861 : : }
862 : :
863 : : #define __LOG_INTERNAL_VA(is_user_context, _src_level, _str, _valist, \
864 : : _argnum, _strdup_action) \
865 : : do { \
866 : : if (is_user_context) { \
867 : : log_generic_from_user(_src_level, _str, _valist); \
868 : : } else if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) { \
869 : : log_generic(_src_level, _str, _valist, _strdup_action); \
870 : : } else if (_argnum == 0) { \
871 : : _LOG_INTERNAL_0(_src_level, _str); \
872 : : } else { \
873 : : uint32_t mask = (_strdup_action != LOG_STRDUP_SKIP) ? \
874 : : z_log_get_s_mask(_str, _argnum) \
875 : : : 0; \
876 : : \
877 : : if (_argnum == 1) { \
878 : : _LOG_INTERNAL_1(_src_level, _str, \
879 : : z_log_do_strdup(mask, 0, \
880 : : va_arg(_valist, log_arg_t), _strdup_action));\
881 : : } else if (_argnum == 2) { \
882 : : _LOG_INTERNAL_2(_src_level, _str, \
883 : : z_log_do_strdup(mask, 0, \
884 : : va_arg(_valist, log_arg_t), _strdup_action), \
885 : : z_log_do_strdup(mask, 1, \
886 : : va_arg(_valist, log_arg_t), _strdup_action));\
887 : : } else if (_argnum == 3) { \
888 : : _LOG_INTERNAL_3(_src_level, _str, \
889 : : z_log_do_strdup(mask, 0, \
890 : : va_arg(_valist, log_arg_t), _strdup_action), \
891 : : z_log_do_strdup(mask, 1, \
892 : : va_arg(_valist, log_arg_t), _strdup_action), \
893 : : z_log_do_strdup(mask, 2, \
894 : : va_arg(_valist, log_arg_t), _strdup_action));\
895 : : } else { \
896 : : log_generic(_src_level, _str, _valist, _strdup_action);\
897 : : } \
898 : : } \
899 : : } while (false)
900 : :
901 : : #include <syscalls/log_core.h>
902 : :
903 : : #ifdef __cplusplus
904 : : }
905 : : #endif
906 : :
907 : : #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_CORE_H_ */
|