Zephyr API Documentation  2.7.0-rc2
A Scalable Open Source RTOS
log_msg2.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_
7#define ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_
8
10#include <sys/mpsc_packet.h>
11#include <sys/cbprintf.h>
12#include <sys/atomic.h>
13#include <sys/util.h>
14#include <string.h>
15
16#ifdef __GNUC__
17#ifndef alloca
18#define alloca __builtin_alloca
19#endif
20#else
21#include <alloca.h>
22#endif
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28#define LOG_MSG2_DEBUG 0
29#define LOG_MSG2_DBG(...) IF_ENABLED(LOG_MSG2_DEBUG, (printk(__VA_ARGS__)))
30
31#if CONFIG_LOG_TIMESTAMP_64BIT
33#else
35#endif
36
44#define Z_LOG_MSG2_LOG 0
45#define Z_LOG_MSG2_TRACE 1
46
47#define LOG_MSG2_GENERIC_HDR \
48 MPSC_PBUF_HDR;\
49 uint32_t type:1
50
58};
59
63#if CONFIG_LOG_TRACE_SHORT_TIMESTAMP
65#else
67#endif
68};
69
73 void *raw;
74};
75
78/* Attempting to keep best alignment. When address is 64 bit and timestamp 32
79 * swap the order to have 16 byte header instead of 24 byte.
80 */
81#if (INTPTR_MAX > INT32_MAX) && !CONFIG_LOG_TIMESTAMP_64BIT
83 const void *source;
84#else
85 const void *source;
87#endif
88#if defined(__xtensa__) && !defined(CONFIG_LOG_TIMESTAMP_64BIT)
89 /* xtensa requires that cbprintf package that follows the header is
90 * aligned to 16 bytes. Adding padding when necessary.
91 */
92 uint32_t padding;
93#endif
94};
95
98};
99
102 void *ptr;
103};
104
105struct log_msg2 {
108};
109
112};
113
119 struct log_msg2 log;
120};
121
126enum z_log_msg2_mode {
127 /* Runtime mode is least efficient but supports all cases thus it is
128 * threated as a fallback method when others cannot be used.
129 */
130 Z_LOG_MSG2_MODE_RUNTIME,
131 /* Mode creates statically a string package on stack and calls a
132 * function for creating a message. It takes code size than
133 * Z_LOG_MSG2_MODE_ZERO_COPY but is a bit slower.
134 */
135 Z_LOG_MSG2_MODE_FROM_STACK,
136
137 /* Mode calculates size of the message and allocates it and writes
138 * directly to the message space. It is the fastest method but requires
139 * more code size.
140 */
141 Z_LOG_MSG2_MODE_ZERO_COPY,
142
143 /* Mode used when synchronous logging is enabled. */
144 Z_LOG_MSG2_MODE_SYNC
145};
146
147#define Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, _plen, _dlen) \
148{ \
149 .valid = 0, \
150 .busy = 0, \
151 .type = Z_LOG_MSG2_LOG, \
152 .domain = _domain_id, \
153 .level = _level, \
154 .package_len = _plen, \
155 .data_len = _dlen, \
156 .reserved = 0, \
157}
158
159/* Messages are aligned to alignment required by cbprintf package. */
160#define Z_LOG_MSG2_ALIGNMENT CBPRINTF_PACKAGE_ALIGNMENT
161
162#if CONFIG_LOG2_USE_VLA
163#define Z_LOG_MSG2_ON_STACK_ALLOC(ptr, len) \
164 long long _ll_buf[ceiling_fraction(len, sizeof(long long))]; \
165 long double _ld_buf[ceiling_fraction(len, sizeof(long double))]; \
166 ptr = (sizeof(long double) == Z_LOG_MSG2_ALIGNMENT) ? \
167 (struct log_msg2 *)_ld_buf : (struct log_msg2 *)_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_MSG2_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_MSG2_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_MSG2_ALIGNMENT) { \
190 ptr = (len > 128) ? (struct log_msg2 *)_ld_buf256 : \
191 ((len > 64) ? (struct log_msg2 *)_ld_buf128 : \
192 ((len > 48) ? (struct log_msg2 *)_ld_buf64 : \
193 ((len > 32) ? (struct log_msg2 *)_ld_buf48 : \
194 (struct log_msg2 *)_ld_buf32)));\
195 } else { \
196 ptr = (len > 128) ? (struct log_msg2 *)_ll_buf256 : \
197 ((len > 64) ? (struct log_msg2 *)_ll_buf128 : \
198 ((len > 48) ? (struct log_msg2 *)_ll_buf64 : \
199 ((len > 32) ? (struct log_msg2 *)_ll_buf48 : \
200 (struct log_msg2 *)_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_MSG2_USE_VLA */
207
208#define Z_LOG_MSG2_ALIGN_OFFSET \
209 sizeof(struct log_msg2_hdr)
210
211#define Z_LOG_MSG2_LEN(pkg_len, data_len) \
212 (sizeof(struct log_msg2_hdr) + pkg_len + (data_len))
213
214#define Z_LOG_MSG2_ALIGNED_WLEN(pkg_len, data_len) \
215 ceiling_fraction(ROUND_UP(Z_LOG_MSG2_LEN(pkg_len, data_len), \
216 Z_LOG_MSG2_ALIGNMENT), \
217 sizeof(uint32_t))
218
219#define Z_LOG_MSG2_SYNC(_domain_id, _source, _level, _data, _dlen, ...) do { \
220 int _plen; \
221 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
222 0, __VA_ARGS__); \
223 struct log_msg2 *_msg; \
224 Z_LOG_MSG2_ON_STACK_ALLOC(_msg, Z_LOG_MSG2_LEN(_plen, _dlen)); \
225 if (_plen) {\
226 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
227 Z_LOG_MSG2_ALIGN_OFFSET, \
228 0, __VA_ARGS__); \
229 } \
230 struct log_msg2_desc _desc = \
231 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
232 (uint32_t)_plen, _dlen); \
233 z_log_msg2_finalize(_msg, _source, _desc, _data); \
234} while (0)
235
236#define Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, _dlen, ...)\
237do { \
238 int _plen; \
239 if (GET_ARG_N(1, __VA_ARGS__) == NULL) { \
240 _plen = 0; \
241 } else { \
242 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
243 0, __VA_ARGS__); \
244 } \
245 struct log_msg2 *_msg; \
246 Z_LOG_MSG2_ON_STACK_ALLOC(_msg, Z_LOG_MSG2_LEN(_plen, 0)); \
247 if (_plen) { \
248 CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, \
249 _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
250 0, __VA_ARGS__);\
251 } \
252 struct log_msg2_desc _desc = \
253 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
254 (uint32_t)_plen, _dlen); \
255 LOG_MSG2_DBG("creating message on stack: package len: %d, data len: %d\n", \
256 _plen, (int)(_dlen)); \
257 z_log_msg2_static_create((void *)_source, _desc, _msg->data, _data); \
258} while (0)
259
260#if CONFIG_LOG_SPEED
261#define Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, _level, ...) do { \
262 int _plen; \
263 CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
264 0, __VA_ARGS__); \
265 size_t _msg_wlen = Z_LOG_MSG2_ALIGNED_WLEN(_plen, 0); \
266 struct log_msg2 *_msg = z_log_msg2_alloc(_msg_wlen); \
267 struct log_msg2_desc _desc = \
268 Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, (uint32_t)_plen, 0); \
269 LOG_MSG2_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_MSG2_ALIGN_OFFSET, \
274 0, __VA_ARGS__); \
275 } \
276 z_log_msg2_finalize(_msg, (void *)_source, _desc, NULL); \
277} while (0)
278#else
279/* Alternative empty macro created to speed up compilation when LOG_SPEED is
280 * disabled (default).
281 */
282#define Z_LOG_MSG2_SIMPLE_CREATE(...)
283#endif
284
285/* Macro handles case when local variable with log message string is created.It
286 * replaces origing string literal with that variable.
287 */
288#define Z_LOG_FMT_ARGS_2(_name, ...) \
289 COND_CODE_1(CONFIG_LOG2_FMT_SECTION, \
290 (COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
291 (_name), (_name, GET_ARGS_LESS_N(1, __VA_ARGS__)))), \
292 (__VA_ARGS__))
293
303#define Z_LOG_FMT_ARGS(_name, ...) \
304 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
305 (NULL), \
306 (Z_LOG_FMT_ARGS_2(_name, ##__VA_ARGS__)))
307
308/* Macro handles case when there is no string provided, in that case variable
309 * is not created.
310 */
311#define Z_LOG_MSG2_STR_VAR_IN_SECTION(_name, ...) \
312 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
313 (/* No args provided, no variable */), \
314 (static const char _name[] \
315 __attribute__((__section__(".log_strings"))) = \
316 GET_ARG_N(1, __VA_ARGS__);))
317
325#define Z_LOG_MSG2_STR_VAR(_name, ...) \
326 IF_ENABLED(CONFIG_LOG2_FMT_SECTION, \
327 (Z_LOG_MSG2_STR_VAR_IN_SECTION(_name, ##__VA_ARGS__)))
328
368#if CONFIG_LOG2_ALWAYS_RUNTIME
369#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
370 _level, _data, _dlen, ...) \
371do {\
372 Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__) \
373 z_log_msg2_runtime_create(_domain_id, (void *)_source, \
374 _level, (uint8_t *)_data, _dlen,\
375 Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
376 _mode = Z_LOG_MSG2_MODE_RUNTIME; \
377} while (0)
378#elif CONFIG_LOG2_MODE_IMMEDIATE /* CONFIG_LOG2_ALWAYS_RUNTIME */
379#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
380 _level, _data, _dlen, ...) \
381do { \
382 Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
383 if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \
384 LOG_MSG2_DBG("create runtime message\n");\
385 z_log_msg2_runtime_create(_domain_id, (void *)_source, \
386 _level, (uint8_t *)_data, _dlen,\
387 Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
388 _mode = Z_LOG_MSG2_MODE_RUNTIME; \
389 } else {\
390 Z_LOG_MSG2_SYNC(_domain_id, _source, _level, \
391 _data, _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
392 _mode = Z_LOG_MSG2_MODE_SYNC; \
393 } \
394} while (0)
395#else /* CONFIG_LOG2_ALWAYS_RUNTIME */
396#define Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, _cstr_cnt, _domain_id, _source,\
397 _level, _data, _dlen, ...) \
398do { \
399 Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
400 if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, __VA_ARGS__)) { \
401 LOG_MSG2_DBG("create runtime message\n");\
402 z_log_msg2_runtime_create(_domain_id, (void *)_source, \
403 _level, (uint8_t *)_data, _dlen,\
404 Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
405 _mode = Z_LOG_MSG2_MODE_RUNTIME; \
406 } else if (IS_ENABLED(CONFIG_LOG_SPEED) && _try_0cpy && ((_dlen) == 0)) {\
407 LOG_MSG2_DBG("create zero-copy message\n");\
408 Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, \
409 _level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
410 _mode = Z_LOG_MSG2_MODE_ZERO_COPY; \
411 } else { \
412 LOG_MSG2_DBG("create on stack message\n");\
413 Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, \
414 _dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
415 _mode = Z_LOG_MSG2_MODE_FROM_STACK; \
416 } \
417 (void)_mode; \
418} while (0)
419#endif /* CONFIG_LOG2_ALWAYS_RUNTIME */
420
421#define Z_LOG_MSG2_CREATE(_try_0cpy, _mode, _domain_id, _source,\
422 _level, _data, _dlen, ...) \
423 Z_LOG_MSG2_CREATE2(_try_0cpy, _mode, UTIL_CAT(Z_LOG_FUNC_PREFIX_, _level), \
424 _domain_id, _source, _level, _data, _dlen, \
425 Z_LOG_STR(_level, __VA_ARGS__))
426
427#define Z_TRACING_LOG_HDR_INIT(name, id) \
428 struct log_msg2_trace name = { \
429 .hdr = { \
430 .type = Z_LOG_MSG2_TRACE, \
431 .valid = 1, \
432 .busy = 0, \
433 .evt_id = id, \
434 } \
435 }
436
450void z_log_msg2_finalize(struct log_msg2 *msg, const void *source,
451 const struct log_msg2_desc desc, const void *data);
452
463__syscall void z_log_msg2_static_create(const void *source,
464 const struct log_msg2_desc desc,
465 uint8_t *package, const void *data);
466
486__syscall void z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
487 uint8_t level, const void *data,
488 size_t dlen, const char *fmt,
489 va_list ap);
490
510static inline void z_log_msg2_runtime_create(uint8_t domain_id,
511 const void *source,
512 uint8_t level, const void *data,
513 size_t dlen, const char *fmt, ...)
514{
515 va_list ap;
516
517 va_start(ap, fmt);
518 z_log_msg2_runtime_vcreate(domain_id, source, level,
519 data, dlen, fmt, ap);
520 va_end(ap);
521}
522
523static inline bool z_log_item_is_msg(union log_msg2_generic *msg)
524{
525 return msg->generic.type == Z_LOG_MSG2_LOG;
526}
527
534static inline uint32_t log_msg2_get_total_wlen(const struct log_msg2_desc desc)
535{
536 return Z_LOG_MSG2_ALIGNED_WLEN(desc.package_len, desc.data_len);
537}
538
546{
547 union log_msg2_generic *generic_msg = (union log_msg2_generic *)item;
548
549 if (z_log_item_is_msg(generic_msg)) {
550 struct log_msg2 *msg = (struct log_msg2 *)generic_msg;
551
552 return log_msg2_get_total_wlen(msg->hdr.desc);
553 }
554
555 /* trace TODO */
556 return 0;
557}
558
565static inline uint8_t log_msg2_get_domain(struct log_msg2 *msg)
566{
567 return msg->hdr.desc.domain;
568}
569
576static inline uint8_t log_msg2_get_level(struct log_msg2 *msg)
577{
578 return msg->hdr.desc.level;
579}
580
587static inline const void *log_msg2_get_source(struct log_msg2 *msg)
588{
589 return msg->hdr.source;
590}
591
599{
600 return msg->hdr.timestamp;
601}
602
611static inline uint8_t *log_msg2_get_data(struct log_msg2 *msg, size_t *len)
612{
613 *len = msg->hdr.desc.data_len;
614
615 return msg->data + msg->hdr.desc.package_len;
616}
617
626static inline uint8_t *log_msg2_get_package(struct log_msg2 *msg, size_t *len)
627{
628 *len = msg->hdr.desc.package_len;
629
630 return msg->data;
631}
632
637#include <syscalls/log_msg2.h>
638
639#ifdef __cplusplus
640}
641#endif
642
643#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_MSG2_H_ */
static const void * log_msg2_get_source(struct log_msg2 *msg)
Get message source data.
Definition: log_msg2.h:587
static uint8_t log_msg2_get_level(struct log_msg2 *msg)
Get log message level.
Definition: log_msg2.h:576
static log_timestamp_t log_msg2_get_timestamp(struct log_msg2 *msg)
Get timestamp.
Definition: log_msg2.h:598
#define LOG_MSG2_GENERIC_HDR
Definition: log_msg2.h:47
static uint8_t * log_msg2_get_package(struct log_msg2 *msg, size_t *len)
Get string package.
Definition: log_msg2.h:626
static uint32_t log_msg2_generic_get_wlen(union mpsc_pbuf_generic *item)
Get length of the log item.
Definition: log_msg2.h:545
static uint8_t * log_msg2_get_data(struct log_msg2 *msg, size_t *len)
Get data buffer.
Definition: log_msg2.h:611
static uint8_t log_msg2_get_domain(struct log_msg2 *msg)
Get log message domain ID.
Definition: log_msg2.h:565
static uint32_t log_msg2_get_total_wlen(const struct log_msg2_desc desc)
Get total length (in 32 bit words) of a log message.
Definition: log_msg2.h:534
uint32_t log_timestamp_t
Definition: log_msg2.h:34
__UINT32_TYPE__ uint32_t
Definition: stdint.h:60
__UINT64_TYPE__ uint64_t
Definition: stdint.h:61
__UINT8_TYPE__ uint8_t
Definition: stdint.h:58
Definition: log_msg2.h:51
uint32_t reserved
Definition: log_msg2.h:57
uint32_t domain
Definition: log_msg2.h:53
uint32_t level
Definition: log_msg2.h:54
uint32_t data_len
Definition: log_msg2.h:56
uint32_t package_len
Definition: log_msg2.h:55
Definition: log_msg2.h:110
uint32_t type
Definition: log_msg2.h:111
Definition: log_msg2.h:76
log_timestamp_t timestamp
Definition: log_msg2.h:86
struct log_msg2_desc desc
Definition: log_msg2.h:77
const void * source
Definition: log_msg2.h:85
Definition: log_msg2.h:60
uint32_t evt_id
Definition: log_msg2.h:62
log_timestamp_t timestamp
Definition: log_msg2.h:66
Definition: log_msg2.h:100
void * ptr
Definition: log_msg2.h:102
struct log_msg2_trace_hdr hdr
Definition: log_msg2.h:101
Definition: log_msg2.h:96
struct log_msg2_trace_hdr hdr
Definition: log_msg2.h:97
Definition: log_msg2.h:105
struct log_msg2_hdr hdr
Definition: log_msg2.h:106
uint8_t data[]
Definition: log_msg2.h:107
Constant data associated with the source of log messages.
Definition: log_instance.h:16
Dynamic data associated with the source of log messages.
Definition: log_instance.h:29
static fdata_t data[2]
Definition: test_fifo_contexts.c:15
Definition: log_msg2.h:114
struct log_msg2_trace_ptr trace_ptr
Definition: log_msg2.h:118
struct log_msg2_trace trace
Definition: log_msg2.h:117
struct log_msg2_generic_hdr generic
Definition: log_msg2.h:116
union mpsc_pbuf_generic buf
Definition: log_msg2.h:115
struct log_msg2 log
Definition: log_msg2.h:119
Definition: log_msg2.h:70
struct log_source_dynamic_data * dynamic
Definition: log_msg2.h:72
const struct log_source_const_data * fixed
Definition: log_msg2.h:71
void * raw
Definition: log_msg2.h:73
Generic packet header.
Definition: mpsc_packet.h:49
Misc utilities.