diff options
Diffstat (limited to 'src/base/logging.hh')
-rw-r--r-- | src/base/logging.hh | 200 |
1 files changed, 98 insertions, 102 deletions
diff --git a/src/base/logging.hh b/src/base/logging.hh index b0a9b0c1b..1c504d22e 100644 --- a/src/base/logging.hh +++ b/src/base/logging.hh @@ -46,113 +46,133 @@ #define __BASE_LOGGING_HH__ #include <cassert> -#include <cstdlib> -#include <iostream> +#include <sstream> #include <utility> #include "base/compiler.hh" #include "base/cprintf.hh" -#if defined(__SUNPRO_CC) -#define __FUNCTION__ "how to fix me?" -#endif - class Logger { public: + + // Get a Logger for the specified type of message. + static Logger &getPanic(); + static Logger &getFatal(); + static Logger &getWarn(); + static Logger &getInfo(); + static Logger &getHack(); + enum LogLevel { - PANIC = 0, - FATAL, - WARN, - INFO, - HACK, + PANIC, FATAL, WARN, INFO, HACK, NUM_LOG_LEVELS, }; - /** - * Set the active log level. - * - * All levels that are lower or equal to the selected log level - * will be activated. - * - * @param ll Maximum log level to print - */ - static void setLevel(LogLevel ll); + static void + setLevel(LogLevel ll) + { + getPanic().enabled = (ll >= PANIC); + getFatal().enabled = (ll >= FATAL); + getWarn().enabled = (ll >= WARN); + getInfo().enabled = (ll >= INFO); + getHack().enabled = (ll >= HACK); + } + + struct Loc + { + Loc(const char *file, int line) : file(file), line(line) {} + const char *file; + int line; + }; - /** - * Get a Logger corresponding to a specific log level - * - * @param ll Log level to access - * @return Reference to the requested logger - */ - static Logger &get(LogLevel ll); + Logger(const char *prefix) : enabled(true), prefix(prefix) + { + assert(prefix); + } - public: - Logger(std::ostream &stream, const char *prefix); virtual ~Logger() {}; - template<typename ...Args> void - print(const char *func, const char *file, int line, - const char *format, const Args &...args) + void + print(const Loc &loc, const std::string &str) { + std::stringstream ss; + ss << prefix << str; + if (str.length() && str.back() != '\n' && str.back() != '\r') + ss << std::endl; if (!enabled) return; + log(loc, ss.str()); + } - if (prefix) - stream << prefix << ": "; - ccprintf(stream, format, args...); - - printEpilogue(func, file, line, format); + template<typename ...Args> void + print(const Loc &loc, const char *format, const Args &...args) + { + std::stringstream ss; + ccprintf(ss, format, args...); + print(loc, ss.str()); } template<typename ...Args> void - print(const char *func, const char *file, int line, - const std::string &format, const Args &...args) + print(const Loc &loc, const std::string &format, const Args &...args) { - print(func, file, line, format.c_str(), args...); + print(loc, format.c_str(), args...); } - protected: - virtual void printEpilogue(const char *func, const char *file, int line, - const char *format); + // This helper is necessary since noreturn isn't inherited by virtual + // functions, and gcc will get mad if a function calls panic and then + // doesn't return. + void exit_helper() M5_ATTR_NORETURN { exit(); ::abort(); } - public: + protected: bool enabled; - bool verbose; - protected: - std::ostream &stream; + virtual void log(const Loc &loc, std::string s) = 0; + virtual void exit() { /* Fall through to the abort in exit_helper. */ } + const char *prefix; }; -#define exit_message(logger, code, ...) \ - do { \ - logger.print(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ - if (code < 0) \ - ::abort(); \ - else \ - ::exit(code); \ + +#define base_message(logger, ...) \ + logger.print(::Logger::Loc(__FILE__, __LINE__), __VA_ARGS__) + +/* + * Only print the message the first time this expression is + * encountered. i.e. This doesn't check the string itself and + * prevent duplicate strings, this prevents the statement from + * happening more than once. So, even if the arguments change and that + * would have resulted in a different message thoes messages would be + * supressed. + */ +#define base_message_once(...) do { \ + static bool once = false; \ + if (!once) { \ + base_message(__VA_ARGS__); \ + once = true; \ + } \ + } while (0) + +#define exit_message(logger, ...) \ + do { \ + base_message(logger, __VA_ARGS__); \ + logger.exit_helper(); \ } while (0) -// -// This implements a cprintf based panic() function. panic() should -// be called when something happens that should never ever happen -// regardless of what the user does (i.e., an acutal m5 bug). panic() -// calls abort which can dump core or enter the debugger. -// -// -#define panic(...) exit_message(::Logger::get(::Logger::PANIC), -1, \ - __VA_ARGS__) +/** + * This implements a cprintf based panic() function. panic() should + * be called when something happens that should never ever happen + * regardless of what the user does (i.e., an acutal m5 bug). panic() + * might call abort which can dump core or enter the debugger. + */ +#define panic(...) exit_message(::Logger::getPanic(), __VA_ARGS__) -// -// This implements a cprintf based fatal() function. fatal() should -// be called when the simulation cannot continue due to some condition -// that is the user's fault (bad configuration, invalid arguments, -// etc.) and not a simulator bug. fatal() calls abort() like -// panic() does. -// -#define fatal(...) exit_message(::Logger::get(::Logger::FATAL), 1, \ - __VA_ARGS__) +/** + * This implements a cprintf based fatal() function. fatal() should + * be called when the simulation cannot continue due to some condition + * that is the user's fault (bad configuration, invalid arguments, + * etc.) and not a simulator bug. fatal() might call exit, unlike panic(). + */ +#define fatal(...) exit_message(::Logger::getFatal(), __VA_ARGS__) /** * Conditional panic macro that checks the supplied condition and only panics @@ -189,37 +209,13 @@ class Logger } while (0) -#define base_message(logger, ...) \ - logger.print(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) - -// Only print the message the first time this expression is -// encountered. i.e. This doesn't check the string itself and -// prevent duplicate strings, this prevents the statement from -// happening more than once. So, even if the arguments change and that -// would have resulted in a different message thoes messages would be -// supressed. -#define base_message_once(...) do { \ - static bool once = false; \ - if (!once) { \ - base_message(__VA_ARGS__); \ - once = true; \ - } \ - } while (0) - - -#define warn(...) \ - base_message(::Logger::get(::Logger::WARN), __VA_ARGS__) -#define inform(...) \ - base_message(::Logger::get(::Logger::INFO), __VA_ARGS__) -#define hack(...) \ - base_message(::Logger::get(::Logger::HACK), __VA_ARGS__) +#define warn(...) base_message(::Logger::getWarn(), __VA_ARGS__) +#define inform(...) base_message(::Logger::getInfo(), __VA_ARGS__) +#define hack(...) base_message(::Logger::getHack(), __VA_ARGS__) -#define warn_once(...) \ - base_message_once(::Logger::get(::Logger::WARN), __VA_ARGS__) -#define inform_once(...) \ - base_message_once(::Logger::get(::Logger::INFO), __VA_ARGS__) -#define hack_once(...) \ - base_message_once(::Logger::get(::Logger::HACK), __VA_ARGS__) +#define warn_once(...) base_message_once(::Logger::getWarn(), __VA_ARGS__) +#define inform_once(...) base_message_once(::Logger::getInfo(), __VA_ARGS__) +#define hack_once(...) base_message_once(::Logger::getHack(), __VA_ARGS__) /** * Conditional warning macro that checks the supplied condition and |