15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Sanjay Ghemawat <opensource@google.com>
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal logging and related utility routines.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef TCMALLOC_INTERNAL_LOGGING_H_
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TCMALLOC_INTERNAL_LOGGING_H_
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h>                     // for size_t
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined HAVE_STDINT_H
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined HAVE_INTTYPES_H
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-------------------------------------------------------------------
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Utility routines
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-------------------------------------------------------------------
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Safe logging helper: we write directly to the stderr file
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptor and avoid FILE buffering because that may invoke
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// malloc().
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Example:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Log(kLog, __FILE__, __LINE__, "error", bytes);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tcmalloc {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum LogMode {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kLog,                       // Just print the message
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kCrash,                     // Print the message and crash
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kCrashWithStats             // Print the message, some stats, and crash
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Logger;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A LogItem holds any of the argument types that can be passed to Log()
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LogItem {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem()                     : tag_(kEnd)      { }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(const char* v)        : tag_(kStr)      { u_.str = v; }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(int v)                : tag_(kSigned)   { u_.snum = v; }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(long v)               : tag_(kSigned)   { u_.snum = v; }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(long long v)          : tag_(kSigned)   { u_.snum = v; }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(unsigned int v)       : tag_(kUnsigned) { u_.unum = v; }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(unsigned long v)      : tag_(kUnsigned) { u_.unum = v; }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(unsigned long long v) : tag_(kUnsigned) { u_.unum = v; }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogItem(const void* v)        : tag_(kPtr)      { u_.ptr = v; }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class Logger;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Tag {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kStr,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kSigned,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kUnsigned,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kPtr,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kEnd
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tag tag_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* str;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* ptr;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64_t snum;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint64_t unum;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern PERFTOOLS_DLL_DECL void Log(LogMode mode, const char* filename, int line,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                LogItem a, LogItem b = LogItem(),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                LogItem c = LogItem(), LogItem d = LogItem());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests can override this function to collect logging messages.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern PERFTOOLS_DLL_DECL void (*log_message_writer)(const char* msg, int length);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // end tcmalloc namespace
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Like assert(), but executed even in NDEBUG mode
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef CHECK_CONDITION
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHECK_CONDITION(cond)                                            \
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)do {                                                                     \
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(cond)) {                                                         \
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, #cond);      \
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }                                                                      \
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHECK_CONDITION_PRINT(cond, str)                                 \
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)do {                                                                     \
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(cond)) {                                                         \
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::tcmalloc::Log(::tcmalloc::kCrash, __FILE__, __LINE__, str);        \
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }                                                                      \
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Our own version of assert() so we can avoid hanging by trying to do
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all kinds of goofy printing while holding the malloc lock.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT(cond) CHECK_CONDITION(cond)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_PRINT(cond, str) CHECK_CONDITION_PRINT(cond, str)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT(cond) ((void) 0)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT_PRINT(cond, str) ((void) 0)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Print into buffer
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TCMalloc_Printer {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf_;           // Where should we write next
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int   left_;          // Space left in buffer (including space for \0)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // REQUIRES: "length > 0"
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TCMalloc_Printer(char* buf, int length) : buf_(buf), left_(length) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf[0] = '\0';
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void printf(const char* format, ...)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE___ATTRIBUTE__
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __attribute__ ((__format__ (__printf__, 2, 3)))
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // TCMALLOC_INTERNAL_LOGGING_H_
153