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 |