blob: 6211e22589dd0eb59752be4886a37690935ec070 [file] [log] [blame]
#ifndef AOS_ATOM_CODE_LOGGING_LOGGING_H_
#define AOS_ATOM_CODE_LOGGING_LOGGING_H_
// IWYU pragma: private, include "aos/common/logging/logging.h"
#ifndef AOS_COMMON_LOGGING_LOGGING_H_
#error This file may only be #included through common/logging/logging.h!!!
#endif
#include "aos/aos_core.h"
#ifdef __cplusplus
extern "C" {
#endif
int log_init(const char *name);
// WARNING: THIS LEAKS MEMORY AND SHARED MEMORY
void log_uninit(void);
extern log_level log_min;
// The basic structure that goes into the shared memory queue.
// It is packed so the pid_t at the front is at the same location as
// the one in log_crio_message.
typedef struct log_message_t_ {
pid_t source;
log_level level;
char message[LOG_MESSAGE_LEN];
char name[40];
struct timespec time;
uint8_t sequence; // per process
} __attribute__((packed)) log_message;
#ifdef __cplusplus
#define LOG_BOOL bool
#else
#define LOG_BOOL uint8_t
#endif
extern LOG_BOOL log_initted;
#undef LOG_BOOL
// Unless explicitly stated otherwise, format must always be a string constant
// and args are printf-style arguments for format.
// The validitiy of format and args together will be checked at compile time
// using a gcc function attribute.
// Logs the specified thing.
#define LOG(level, format, args...) do { \
if (level >= log_min) { \
log_do(level, LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": " format, ##args); \
} \
} while (0)
// Allows "bottling up" multiple log fragments which can then all be logged in
// one message with LOG_UNCORK.
// format does not have to be a constant
#define LOG_CORK(format, args...) do { \
log_cork(__LINE__, format, ##args); \
} while (0)
// Actually logs all of the saved up log fragments (including format and args on
// the end).
#define LOG_UNCORK(level, format, args...) do { \
log_uncork(__LINE__, level, LOG_SOURCENAME ": %d-%d: ", format, ##args); \
} while (0)
// Makes a normal logging call if possible or just prints it out on stderr.
#define LOG_IFINIT(level, format, args...) do{ \
if(log_initted) { \
LOG(level, format, args); \
} else { \
fprintf(stderr, "%s-noinit: " format, log_str(level), ##args); \
} \
}while(0)
// All functions return 0 for success and - for error.
// Actually implements the basic logging call.
// Does not check that level is valid.
// TODO(brians): Fix this so it works with clang.
int log_do(log_level level, const char *format, ...)
__attribute__((format(gnu_printf, 2, 3)));
// TODO(brians): Fix this so it works with clang.
int log_cork(int line, const char *format, ...)
__attribute__((format(gnu_printf, 2, 3)));
// Implements the uncork logging call.
// IMPORTANT: begin_format must have 2 %d formats as its only 2 format specifiers
// which will get passed the minimum and maximum line numbers that have been
// corked into this call.
// TODO(brians): Fix this so it works with clang.
int log_uncork(int line, log_level level, const char *begin_format,
const char *format, ...)
__attribute__((format(gnu_printf, 4, 5)));
const log_message *log_read_next1(int flags);
const log_message *log_read_next2(int flags, int *index);
inline const log_message *log_read_next(void) { return log_read_next1(BLOCK); }
void log_free_message(const log_message *msg);
// The structure that is actually in the shared memory queue.
union log_queue_message {
log_message atom;
log_crio_message crio;
};
#ifdef __cplusplus
}
#endif
#endif