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 |
40 | 47 |
41 //------------------------------------------------------------------- | 48 //------------------------------------------------------------------- |
42 // Utility routines | 49 // Utility routines |
43 //------------------------------------------------------------------- | 50 //------------------------------------------------------------------- |
44 | 51 |
45 // Safe debugging routine: we write directly to the stderr file | 52 // Safe logging helper: we write directly to the stderr file |
46 // descriptor and avoid FILE buffering because that may invoke | 53 // descriptor and avoid FILE buffering because that may invoke |
47 // malloc() | 54 // malloc(). |
48 extern void TCMalloc_MESSAGE(const char* filename, | 55 // |
49 int line_number, | 56 // Example: |
50 const char* format, ...) | 57 // Log(kLog, __FILE__, __LINE__, "error", bytes); |
51 #ifdef HAVE___ATTRIBUTE__ | |
52 __attribute__ ((__format__ (__printf__, 3, 4))) | |
53 #endif | |
54 ; | |
55 | 58 |
56 // Right now, the only non-fatal messages we want to report are when | 59 namespace tcmalloc { |
57 // an allocation fails (we'll return NULL eventually, but sometimes | 60 enum LogMode { |
58 // want more prominent notice to help debug). message should be | 61 kLog, // Just print the message |
59 // a literal string with no %<whatever> format directives. | 62 kCrash, // Print the message and crash |
60 #ifdef TCMALLOC_WARNINGS | 63 kCrashWithStats // Print the message, some stats, and crash |
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_; | |
97 }; | 64 }; |
98 | 65 |
99 #define CRASH \ | 66 class Logger; |
100 TCMalloc_CrashReporter(false, __FILE__, __LINE__).PrintfAndDie | |
101 | 67 |
102 #define CRASH_WITH_STATS \ | 68 // A LogItem holds any of the argument types that can be passed to Log() |
103 TCMalloc_CrashReporter(true, __FILE__, __LINE__).PrintfAndDie | 69 class LogItem { |
| 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 |
104 | 106 |
105 // Like assert(), but executed even in NDEBUG mode | 107 // Like assert(), but executed even in NDEBUG mode |
106 #undef CHECK_CONDITION | 108 #undef CHECK_CONDITION |
107 #define CHECK_CONDITION(cond) \ | 109 #define CHECK_CONDITION(cond) \ |
108 do { \ | 110 do { \ |
109 if (!(cond)) { \ | 111 if (!(cond)) { \ |
110 CRASH("assertion failed: %s\n", #cond); \ | 112 ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, #cond); \ |
111 } \ | 113 } \ |
112 } while (0) | 114 } while (0) |
113 | 115 |
114 // Our own version of assert() so we can avoid hanging by trying to do | 116 // Our own version of assert() so we can avoid hanging by trying to do |
115 // all kinds of goofy printing while holding the malloc lock. | 117 // all kinds of goofy printing while holding the malloc lock. |
116 #ifndef NDEBUG | 118 #ifndef NDEBUG |
117 #define ASSERT(cond) CHECK_CONDITION(cond) | 119 #define ASSERT(cond) CHECK_CONDITION(cond) |
118 #else | 120 #else |
119 #define ASSERT(cond) ((void) 0) | 121 #define ASSERT(cond) ((void) 0) |
120 #endif | 122 #endif |
(...skipping 11 matching lines...) Expand all Loading... |
132 } | 134 } |
133 | 135 |
134 void printf(const char* format, ...) | 136 void printf(const char* format, ...) |
135 #ifdef HAVE___ATTRIBUTE__ | 137 #ifdef HAVE___ATTRIBUTE__ |
136 __attribute__ ((__format__ (__printf__, 2, 3))) | 138 __attribute__ ((__format__ (__printf__, 2, 3))) |
137 #endif | 139 #endif |
138 ; | 140 ; |
139 }; | 141 }; |
140 | 142 |
141 #endif // TCMALLOC_INTERNAL_LOGGING_H_ | 143 #endif // TCMALLOC_INTERNAL_LOGGING_H_ |
OLD | NEW |