Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2005, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // ---
     31 // Author: Sanjay Ghemawat <opensource (at) google.com>
     32 //
     33 // Internal logging and related utility routines.
     34 
     35 #ifndef TCMALLOC_INTERNAL_LOGGING_H_
     36 #define TCMALLOC_INTERNAL_LOGGING_H_
     37 
     38 #include <config.h>
     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 
     48 //-------------------------------------------------------------------
     49 // Utility routines
     50 //-------------------------------------------------------------------
     51 
     52 // Safe logging helper: we write directly to the stderr file
     53 // descriptor and avoid FILE buffering because that may invoke
     54 // malloc().
     55 //
     56 // Example:
     57 //   Log(kLog, __FILE__, __LINE__, "error", bytes);
     58 
     59 namespace tcmalloc {
     60 enum LogMode {
     61   kLog,                       // Just print the message
     62   kCrash,                     // Print the message and crash
     63   kCrashWithStats             // Print the message, some stats, and crash
     64 };
     65 
     66 class Logger;
     67 
     68 // A LogItem holds any of the argument types that can be passed to Log()
     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
    106 
    107 // Like assert(), but executed even in NDEBUG mode
    108 #undef CHECK_CONDITION
    109 #define CHECK_CONDITION(cond)                                            \
    110 do {                                                                     \
    111   if (!(cond)) {                                                         \
    112     ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, #cond);      \
    113   }                                                                      \
    114 } while (0)
    115 
    116 #define CHECK_CONDITION_PRINT(cond, str)                                 \
    117 do {                                                                     \
    118   if (!(cond)) {                                                         \
    119     ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, str);        \
    120   }                                                                      \
    121 } while (0)
    122 
    123 // Our own version of assert() so we can avoid hanging by trying to do
    124 // all kinds of goofy printing while holding the malloc lock.
    125 #ifndef NDEBUG
    126 #define ASSERT(cond) CHECK_CONDITION(cond)
    127 #define ASSERT_PRINT(cond, str) CHECK_CONDITION_PRINT(cond, str)
    128 #else
    129 #define ASSERT(cond) ((void) 0)
    130 #define ASSERT_PRINT(cond, str) ((void) 0)
    131 #endif
    132 
    133 // Print into buffer
    134 class TCMalloc_Printer {
    135  private:
    136   char* buf_;           // Where should we write next
    137   int   left_;          // Space left in buffer (including space for \0)
    138 
    139  public:
    140   // REQUIRES: "length > 0"
    141   TCMalloc_Printer(char* buf, int length) : buf_(buf), left_(length) {
    142     buf[0] = '\0';
    143   }
    144 
    145   void printf(const char* format, ...)
    146 #ifdef HAVE___ATTRIBUTE__
    147     __attribute__ ((__format__ (__printf__, 2, 3)))
    148 #endif
    149 ;
    150 };
    151 
    152 #endif  // TCMALLOC_INTERNAL_LOGGING_H_
    153