| OLD | NEW |
| 1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 // --- | 30 // --- |
| 31 // Author: Sanjay Ghemawat <opensource@google.com> | 31 // Author: Sanjay Ghemawat <opensource@google.com> |
| 32 // | 32 // |
| 33 // Internal logging and related utility routines. | 33 // Internal logging and related utility routines. |
| 34 | 34 |
| 35 #ifndef TCMALLOC_INTERNAL_LOGGING_H_ | 35 #ifndef TCMALLOC_INTERNAL_LOGGING_H_ |
| 36 #define TCMALLOC_INTERNAL_LOGGING_H_ | 36 #define TCMALLOC_INTERNAL_LOGGING_H_ |
| 37 | 37 |
| 38 #include <config.h> | 38 #include <config.h> |
| 39 #include <stddef.h> // for size_t | 39 #include <stddef.h> // for size_t |
| 40 #if defined HAVE_STDINT_H | |
| 41 #include <stdint.h> | |
| 42 #elif defined HAVE_INTTYPES_H | |
| 43 #include <inttypes.h> | |
| 44 #else | |
| 45 #include <sys/types.h> | |
| 46 #endif | |
| 47 | 40 |
| 48 //------------------------------------------------------------------- | 41 //------------------------------------------------------------------- |
| 49 // Utility routines | 42 // Utility routines |
| 50 //------------------------------------------------------------------- | 43 //------------------------------------------------------------------- |
| 51 | 44 |
| 52 // Safe logging helper: we write directly to the stderr file | 45 // Safe debugging routine: we write directly to the stderr file |
| 53 // descriptor and avoid FILE buffering because that may invoke | 46 // descriptor and avoid FILE buffering because that may invoke |
| 54 // malloc(). | 47 // malloc() |
| 55 // | 48 extern void TCMalloc_MESSAGE(const char* filename, |
| 56 // Example: | 49 int line_number, |
| 57 // Log(kLog, __FILE__, __LINE__, "error", bytes); | 50 const char* format, ...) |
| 51 #ifdef HAVE___ATTRIBUTE__ |
| 52 __attribute__ ((__format__ (__printf__, 3, 4))) |
| 53 #endif |
| 54 ; |
| 58 | 55 |
| 59 namespace tcmalloc { | 56 // Right now, the only non-fatal messages we want to report are when |
| 60 enum LogMode { | 57 // an allocation fails (we'll return NULL eventually, but sometimes |
| 61 kLog, // Just print the message | 58 // want more prominent notice to help debug). message should be |
| 62 kCrash, // Print the message and crash | 59 // a literal string with no %<whatever> format directives. |
| 63 kCrashWithStats // Print the message, some stats, and crash | 60 #ifdef TCMALLOC_WARNINGS |
| 61 #define MESSAGE(message, num_bytes) \ |
| 62 TCMalloc_MESSAGE(__FILE__, __LINE__, message " (%"PRIuS" bytes)\n", \ |
| 63 static_cast<size_t>(num_bytes)) |
| 64 #else |
| 65 #define MESSAGE(message, num_bytes) |
| 66 #endif |
| 67 |
| 68 // Dumps the specified message and then calls abort(). If |
| 69 // "dump_stats" is specified, the first call will also dump the |
| 70 // tcmalloc stats. |
| 71 extern void TCMalloc_CRASH(bool dump_stats, |
| 72 const char* filename, |
| 73 int line_number, |
| 74 const char* format, ...) |
| 75 #ifdef HAVE___ATTRIBUTE__ |
| 76 __attribute__ ((__format__ (__printf__, 4, 5))) |
| 77 #endif |
| 78 ; |
| 79 |
| 80 // This is a class that makes using the macro easier. With this class, |
| 81 // CRASH("%d", i) expands to TCMalloc_CrashReporter.PrintfAndDie("%d", i). |
| 82 class PERFTOOLS_DLL_DECL TCMalloc_CrashReporter { |
| 83 public: |
| 84 TCMalloc_CrashReporter(bool dump_stats, const char* file, int line) |
| 85 : dump_stats_(dump_stats), file_(file), line_(line) { |
| 86 } |
| 87 void PrintfAndDie(const char* format, ...) |
| 88 #ifdef HAVE___ATTRIBUTE__ |
| 89 __attribute__ ((__format__ (__printf__, 2, 3))) // 2,3 due to "this" |
| 90 #endif |
| 91 ; |
| 92 |
| 93 private: |
| 94 bool dump_stats_; |
| 95 const char* file_; |
| 96 int line_; |
| 64 }; | 97 }; |
| 65 | 98 |
| 66 class Logger; | 99 #define CRASH \ |
| 100 TCMalloc_CrashReporter(false, __FILE__, __LINE__).PrintfAndDie |
| 67 | 101 |
| 68 // A LogItem holds any of the argument types that can be passed to Log() | 102 #define CRASH_WITH_STATS \ |
| 69 class LogItem { | 103 TCMalloc_CrashReporter(true, __FILE__, __LINE__).PrintfAndDie |
| 70 public: | |
| 71 LogItem() : tag_(kEnd) { } | |
| 72 LogItem(const char* v) : tag_(kStr) { u_.str = v; } | |
| 73 LogItem(int v) : tag_(kSigned) { u_.snum = v; } | |
| 74 LogItem(long v) : tag_(kSigned) { u_.snum = v; } | |
| 75 LogItem(long long v) : tag_(kSigned) { u_.snum = v; } | |
| 76 LogItem(unsigned int v) : tag_(kUnsigned) { u_.unum = v; } | |
| 77 LogItem(unsigned long v) : tag_(kUnsigned) { u_.unum = v; } | |
| 78 LogItem(unsigned long long v) : tag_(kUnsigned) { u_.unum = v; } | |
| 79 LogItem(const void* v) : tag_(kPtr) { u_.ptr = v; } | |
| 80 private: | |
| 81 friend class Logger; | |
| 82 enum Tag { | |
| 83 kStr, | |
| 84 kSigned, | |
| 85 kUnsigned, | |
| 86 kPtr, | |
| 87 kEnd | |
| 88 }; | |
| 89 Tag tag_; | |
| 90 union { | |
| 91 const char* str; | |
| 92 const void* ptr; | |
| 93 int64_t snum; | |
| 94 uint64_t unum; | |
| 95 } u_; | |
| 96 }; | |
| 97 | |
| 98 extern PERFTOOLS_DLL_DECL void Log(LogMode mode, const char* filename, int line, | |
| 99 LogItem a, LogItem b = LogItem(), | |
| 100 LogItem c = LogItem(), LogItem d = LogItem()); | |
| 101 | |
| 102 // Tests can override this function to collect logging messages. | |
| 103 extern PERFTOOLS_DLL_DECL void (*log_message_writer)(const char* msg, int length
); | |
| 104 | |
| 105 } // end tcmalloc namespace | |
| 106 | 104 |
| 107 // Like assert(), but executed even in NDEBUG mode | 105 // Like assert(), but executed even in NDEBUG mode |
| 108 #undef CHECK_CONDITION | 106 #undef CHECK_CONDITION |
| 109 #define CHECK_CONDITION(cond) \ | 107 #define CHECK_CONDITION(cond) \ |
| 110 do { \ | 108 do { \ |
| 111 if (!(cond)) { \ | 109 if (!(cond)) { \ |
| 112 ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, #cond); \ | 110 CRASH("assertion failed: %s\n", #cond); \ |
| 113 } \ | 111 } \ |
| 114 } while (0) | 112 } while (0) |
| 115 | 113 |
| 116 // Our own version of assert() so we can avoid hanging by trying to do | 114 // Our own version of assert() so we can avoid hanging by trying to do |
| 117 // all kinds of goofy printing while holding the malloc lock. | 115 // all kinds of goofy printing while holding the malloc lock. |
| 118 #ifndef NDEBUG | 116 #ifndef NDEBUG |
| 119 #define ASSERT(cond) CHECK_CONDITION(cond) | 117 #define ASSERT(cond) CHECK_CONDITION(cond) |
| 120 #else | 118 #else |
| 121 #define ASSERT(cond) ((void) 0) | 119 #define ASSERT(cond) ((void) 0) |
| 122 #endif | 120 #endif |
| (...skipping 11 matching lines...) Expand all Loading... |
| 134 } | 132 } |
| 135 | 133 |
| 136 void printf(const char* format, ...) | 134 void printf(const char* format, ...) |
| 137 #ifdef HAVE___ATTRIBUTE__ | 135 #ifdef HAVE___ATTRIBUTE__ |
| 138 __attribute__ ((__format__ (__printf__, 2, 3))) | 136 __attribute__ ((__format__ (__printf__, 2, 3))) |
| 139 #endif | 137 #endif |
| 140 ; | 138 ; |
| 141 }; | 139 }; |
| 142 | 140 |
| 143 #endif // TCMALLOC_INTERNAL_LOGGING_H_ | 141 #endif // TCMALLOC_INTERNAL_LOGGING_H_ |
| OLD | NEW |