log.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #ifndef LOG_H
  2. #define LOG_H
  3. #include "fixed_types.h"
  4. #include "lock.h"
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <set>
  8. #include <map>
  9. class Config;
  10. class Log
  11. {
  12. public:
  13. Log(Config &config);
  14. ~Log();
  15. static Log *getSingleton();
  16. enum ErrorState
  17. {
  18. None,
  19. Warning,
  20. Error,
  21. };
  22. void log(ErrorState err, const char *source_file, SInt32 source_line, const char* format, ...);
  23. bool isEnabled(const char* module);
  24. bool isLoggingEnabled() const { return _anyLoggingEnabled; }
  25. String getModule(const char *filename);
  26. private:
  27. UInt64 getTimestamp();
  28. void initFileDescriptors();
  29. static void parseModules(std::set<String> &mods, String list);
  30. void getDisabledModules();
  31. void getEnabledModules();
  32. bool initIsLoggingEnabled();
  33. void discoverCore(core_id_t *core_id, bool *sim_thread);
  34. void getFile(core_id_t core_id, bool sim_thread, FILE ** f, Lock ** l);
  35. ErrorState _state;
  36. // when core id is known
  37. FILE** _coreFiles;
  38. FILE** _simFiles;
  39. Lock* _coreLocks;
  40. Lock *_simLocks;
  41. // when core is id unknown but process # is
  42. FILE* _systemFile;
  43. Lock _systemLock;
  44. core_id_t _coreCount;
  45. UInt64 _startTime;
  46. std::set<String> _disabledModules;
  47. std::set<String> _enabledModules;
  48. bool _loggingEnabled;
  49. bool _anyLoggingEnabled;
  50. /* std::map<const char*, String> _modules; */
  51. /* Lock _modules_lock; */
  52. static const size_t MODULE_LENGTH = 20;
  53. static Log *_singleton;
  54. };
  55. // Macros
  56. #ifdef NDEBUG
  57. // see assert.h
  58. #define __LOG_PRINT(...) ((void)(0))
  59. #define _LOG_PRINT(...) ((void)(0))
  60. #define LOG_PRINT(...) ((void)(0))
  61. #define LOG_PRINT_WARNING(...) ((void)(0))
  62. #define LOG_PRINT_WARNING_ONCE(...) ((void)(0))
  63. #define LOG_PRINT_ERROR(...) (exit(-1)) // call exit() to inherit its __attribute__ ((__noreturn__))
  64. #define LOG_ASSERT_WARNING(...) ((void)(0))
  65. #define LOG_ASSERT_WARNING_ONCE(...) ((void)(0))
  66. #define LOG_ASSERT_ERROR(...) ((void)(0))
  67. #else
  68. #define likely(x) __builtin_expect((x), 1)
  69. #define unlikely(x) __builtin_expect((x), 0)
  70. #define __LOG_PRINT(err, file, line, ...) \
  71. { \
  72. if (unlikely(Log::getSingleton()->isLoggingEnabled()) || err != Log::None) \
  73. { \
  74. String module = Log::getSingleton()->getModule(file); \
  75. if (err != Log::None || \
  76. Log::getSingleton()->isEnabled(module.c_str())) \
  77. { \
  78. Log::getSingleton()->log(err, module.c_str(), line, __VA_ARGS__); \
  79. } \
  80. } \
  81. } \
  82. #define _LOG_PRINT(err, ...) \
  83. { \
  84. __LOG_PRINT(err, __FILE__, __LINE__, __VA_ARGS__); \
  85. } \
  86. #define LOG_PRINT(...) \
  87. _LOG_PRINT(Log::None, __VA_ARGS__); \
  88. #define LOG_PRINT_WARNING(...) \
  89. _LOG_PRINT(Log::Warning, __VA_ARGS__);
  90. #define LOG_PRINT_WARNING_ONCE(...) \
  91. { \
  92. static bool already_printed = false; \
  93. if (!already_printed) \
  94. { \
  95. _LOG_PRINT(Log::Warning, __VA_ARGS__); \
  96. _LOG_PRINT(Log::Warning, "Future warnings of this type will be suppressed."); \
  97. already_printed = true; \
  98. } \
  99. }
  100. // _LOG_PRINT(Log::Error) does not return, but the compiler doesn't know this which can result in
  101. // ''control reaches end of non-void function'' warnings in places where the LOG_PRINT_ASSERT(false) idiom is used.
  102. // We cannot easily add __attribute__ ((__noreturn__)) to the LOG_PRINT_ERROR macro
  103. // since that only works on functions, and we have the added complexity of passing the ... argument around.
  104. // Adding exit() to the end of LOG_PRINT_ERROR effectively makes it inherit exit's __noreturn__
  105. // which suppresses the warning (even though the exit() itself isn't executed as it's never reached).
  106. #define LOG_PRINT_ERROR(...) \
  107. { \
  108. _LOG_PRINT(Log::Error, __VA_ARGS__); \
  109. exit(-1); \
  110. }
  111. #define LOG_ASSERT_WARNING(expr, ...) \
  112. { \
  113. if (!(expr)) \
  114. { \
  115. LOG_PRINT_WARNING(__VA_ARGS__); \
  116. } \
  117. } \
  118. #define LOG_ASSERT_WARNING_ONCE(expr, ...) \
  119. { \
  120. if (!(expr)) \
  121. { \
  122. LOG_PRINT_WARNING_ONCE(__VA_ARGS__); \
  123. } \
  124. } \
  125. #define LOG_ASSERT_ERROR(expr, ...) \
  126. { \
  127. if (!(expr)) \
  128. { \
  129. LOG_PRINT_ERROR(__VA_ARGS__); \
  130. } \
  131. } \
  132. #endif // NDEBUG
  133. // Helpers
  134. class FunctionTracer
  135. {
  136. public:
  137. FunctionTracer(const char *file, int line, const char *fn)
  138. : m_file(file)
  139. , m_line(line)
  140. , m_fn(fn)
  141. {
  142. __LOG_PRINT(Log::None, m_file, m_line, "Entering: %s", m_fn);
  143. }
  144. ~FunctionTracer()
  145. {
  146. __LOG_PRINT(Log::None, m_file, m_line, "Exiting: %s", m_fn);
  147. }
  148. private:
  149. const char *m_file;
  150. int m_line;
  151. const char *m_fn;
  152. };
  153. #define LOG_FUNC_TRACE() FunctionTracer func_tracer(__FILE__,__LINE__,__PRETTY_FUNCTION__);
  154. #endif // LOG_H