logging: add minimal implementation

The log mechanism, even in immediate mode, adds somewhere
between 1K-2K of footprint to applications that use it.

We want to standardize the logging APIs for all logging
within the kernel, but need to not let platforms with
very constrained RAM/ROM in the dust.

This patch introduces CONFIG_LOG_MINIMAL, which is a very
thin wrapper to printk(). It supports the APIs expressed
in logging/log.h.

This will be the new default for test cases.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-09-22 16:44:43 -07:00 committed by Anas Nashif
commit 7e29c9da0b
7 changed files with 222 additions and 94 deletions

View file

@ -28,12 +28,6 @@ extern "C" {
* @{
*/
#define LOG_LEVEL_NONE 0
#define LOG_LEVEL_ERR 1
#define LOG_LEVEL_WRN 2
#define LOG_LEVEL_INF 3
#define LOG_LEVEL_DBG 4
/**
* @brief Writes an ERROR level message to the log.
*
@ -247,6 +241,7 @@ extern "C" {
#define LOG_INST_HEXDUMP_DBG(_log_inst, _data, _length, _str) \
Z_LOG_HEXDUMP_INSTANCE(LOG_LEVEL_DBG, _log_inst, _data, _length, _str)
#ifndef CONFIG_LOG_MINIMAL
/**
* @brief Writes an formatted string to the log.
*
@ -266,13 +261,29 @@ void log_printk(const char *fmt, va_list ap);
* Logger allocates a buffer and copies input string returning a pointer to the
* copy. Logger ensures that buffer is freed when logger message is freed.
*
* Depending on configuration, this function may do nothing and just pass
* along the supplied string pointer. Do not rely on this function to always
* make a copy!
*
* @param str Transient string.
*
* @return Copy of the string or default string if buffer could not be
* allocated. String may be truncated if input string does not fit in
* a buffer from the pool (see CONFIG_LOG_STRDUP_MAX_STRING).
* a buffer from the pool (see CONFIG_LOG_STRDUP_MAX_STRING). In
* some configurations, the original string pointer is returned.
*/
char *log_strdup(const char *str);
#else
static inline void log_printk(const char *fmt, va_list ap)
{
vprintk(fmt, ap);
}
static inline char *log_strdup(const char *str)
{
return (char *)str;
}
#endif /* CONFIG_LOG_MINIMAL */
#ifdef __cplusplus
}

View file

@ -13,6 +13,13 @@
#include <stdarg.h>
#include <syscall.h>
#include <sys/util.h>
#include <sys/printk.h>
#define LOG_LEVEL_NONE 0
#define LOG_LEVEL_ERR 1
#define LOG_LEVEL_WRN 2
#define LOG_LEVEL_INF 3
#define LOG_LEVEL_DBG 4
#ifdef __cplusplus
extern "C" {
@ -20,10 +27,13 @@ extern "C" {
#ifndef CONFIG_LOG
#define CONFIG_LOG_DEFAULT_LEVEL 0
#define CONFIG_LOG_DOMAIN_ID 0
#define CONFIG_LOG_MAX_LEVEL 0
#endif
#if !defined(CONFIG_LOG) || defined(CONFIG_LOG_MINIMAL)
#define CONFIG_LOG_DOMAIN_ID 0
#endif
#define LOG_FUNCTION_PREFIX_MASK \
(((u32_t)IS_ENABLED(CONFIG_LOG_FUNC_NAME_PREFIX_ERR) << \
LOG_LEVEL_ERR) | \
@ -210,35 +220,67 @@ extern "C" {
) \
))
/******************************************************************************/
/****************** Defiinitions used by minimal logging **********************/
/******************************************************************************/
void log_minimal_hexdump_print(int level, const char *data, size_t size);
#define Z_LOG_TO_PRINTK(_level, fmt, ...) do { \
printk("%c: " fmt "\n", z_log_minimal_level_to_char(_level), \
##__VA_ARGS__); \
} while (false)
static inline char z_log_minimal_level_to_char(int level)
{
switch (level) {
case LOG_LEVEL_ERR:
return 'E';
case LOG_LEVEL_WRN:
return 'W';
case LOG_LEVEL_INF:
return 'I';
case LOG_LEVEL_DBG:
return 'D';
default:
return '?';
}
}
/******************************************************************************/
/****************** Macros for standard logging *******************************/
/******************************************************************************/
#define __LOG(_level, _id, _filter, ...) \
do { \
bool is_user_context = _is_user_context(); \
\
if (Z_LOG_CONST_LEVEL_CHECK(_level) && \
(is_user_context || \
(_level <= LOG_RUNTIME_FILTER(_filter)))) { \
struct log_msg_ids src_level = { \
.level = _level, \
.domain_id = CONFIG_LOG_DOMAIN_ID, \
.source_id = _id \
}; \
\
if ((BIT(_level) & LOG_FUNCTION_PREFIX_MASK) != 0U) {\
__LOG_INTERNAL(is_user_context, src_level, \
Z_LOG_STR(__VA_ARGS__)); \
} else { \
__LOG_INTERNAL(is_user_context, src_level, \
__VA_ARGS__); \
} \
} else if (false) { \
/* Arguments checker present but never evaluated.*/ \
/* Placed here to ensure that __VA_ARGS__ are*/ \
/* evaluated once when log is enabled.*/ \
log_printf_arg_checker(__VA_ARGS__); \
} \
#define __LOG(_level, _id, _filter, ...) \
do { \
bool is_user_context = _is_user_context(); \
\
if (Z_LOG_CONST_LEVEL_CHECK(_level)) { \
if (IS_ENABLED(CONFIG_LOG_MINIMAL)) { \
Z_LOG_TO_PRINTK(_level, __VA_ARGS__); \
} else if (is_user_context || \
(_level <= LOG_RUNTIME_FILTER(_filter))) { \
struct log_msg_ids src_level = { \
.level = _level, \
.domain_id = CONFIG_LOG_DOMAIN_ID, \
.source_id = _id \
}; \
\
if ((BIT(_level) & \
LOG_FUNCTION_PREFIX_MASK) != 0U) { \
__LOG_INTERNAL(is_user_context, \
src_level, \
Z_LOG_STR(__VA_ARGS__));\
} else { \
__LOG_INTERNAL(is_user_context, \
src_level, \
__VA_ARGS__); \
} \
} \
} \
if (false) { \
/* Arguments checker present but never evaluated.*/ \
/* Placed here to ensure that __VA_ARGS__ are*/ \
/* evaluated once when log is enabled.*/ \
log_printf_arg_checker(__VA_ARGS__); \
} \
} while (false)
#define Z_LOG(_level, ...) \
@ -259,29 +301,35 @@ extern "C" {
/******************************************************************************/
/****************** Macros for hexdump logging ********************************/
/******************************************************************************/
#define __LOG_HEXDUMP(_level, _id, _filter, _data, _length, _str) \
do { \
bool is_user_context = _is_user_context(); \
\
if (Z_LOG_CONST_LEVEL_CHECK(_level) && \
(is_user_context || \
(_level <= LOG_RUNTIME_FILTER(_filter)))) { \
struct log_msg_ids src_level = { \
.level = _level, \
.source_id = _id, \
.domain_id = CONFIG_LOG_DOMAIN_ID \
}; \
\
if (is_user_context) { \
log_hexdump_from_user(src_level, _str, \
_data, _length); \
} else if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) { \
log_hexdump_sync(src_level, _str, \
_data, _length); \
} else { \
log_hexdump(_str, _data, _length, src_level); \
} \
} \
#define __LOG_HEXDUMP(_level, _id, _filter, _data, _length, _str) \
do { \
bool is_user_context = _is_user_context(); \
\
if (Z_LOG_CONST_LEVEL_CHECK(_level)) { \
if (IS_ENABLED(CONFIG_LOG_MINIMAL)) { \
Z_LOG_TO_PRINTK(_level, "%s", _str); \
log_minimal_hexdump_print(_level, _data, \
_length); \
} else if (is_user_context || \
(_level <= LOG_RUNTIME_FILTER(_filter))) { \
struct log_msg_ids src_level = { \
.level = _level, \
.source_id = _id, \
.domain_id = CONFIG_LOG_DOMAIN_ID \
}; \
\
if (is_user_context) { \
log_hexdump_from_user(src_level, _str, \
_data, _length); \
} else if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) { \
log_hexdump_sync(src_level, _str, \
_data, _length); \
} else { \
log_hexdump(_str, _data, _length, \
src_level); \
} \
} \
} \
} while (false)
#define Z_LOG_HEXDUMP(_level, _data, _length, _str) \

View file

@ -169,7 +169,7 @@ void log_backend_enable(struct log_backend const *const backend,
*/
void log_backend_disable(struct log_backend const *const backend);
#if defined(CONFIG_LOG)
#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MINIMAL)
#define LOG_CORE_INIT() log_core_init()
#define LOG_INIT() log_init()
#define LOG_PANIC() log_panic()