logging.h revision 43b2e0f9105848da6470458e7c04bf1fd7fcb25c
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_RUNTIME_BASE_LOGGING_H_ 18#define ART_RUNTIME_BASE_LOGGING_H_ 19 20#include <cerrno> 21#include <cstring> 22#include <iostream> // NOLINT 23#include <sstream> 24#include <signal.h> 25#include "base/macros.h" 26#include "log_severity.h" 27#include "UniquePtr.h" 28 29#define CHECK(x) \ 30 if (UNLIKELY(!(x))) \ 31 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \ 32 << "Check failed: " #x << " " 33 34#define CHECK_OP(LHS, RHS, OP) \ 35 for (auto _values = ::art::MakeEagerEvaluator(LHS, RHS); \ 36 UNLIKELY(!(_values.lhs OP _values.rhs)); /* empty */) \ 37 ::art::LogMessage(__FILE__, __LINE__, FATAL, -1).stream() \ 38 << "Check failed: " << #LHS << " " << #OP << " " << #RHS \ 39 << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") " 40 41#define CHECK_EQ(x, y) CHECK_OP(x, y, ==) 42#define CHECK_NE(x, y) CHECK_OP(x, y, !=) 43#define CHECK_LE(x, y) CHECK_OP(x, y, <=) 44#define CHECK_LT(x, y) CHECK_OP(x, y, <) 45#define CHECK_GE(x, y) CHECK_OP(x, y, >=) 46#define CHECK_GT(x, y) CHECK_OP(x, y, >) 47 48#define CHECK_STROP(s1, s2, sense) \ 49 if (UNLIKELY((strcmp(s1, s2) == 0) != sense)) \ 50 LOG(FATAL) << "Check failed: " \ 51 << "\"" << s1 << "\"" \ 52 << (sense ? " == " : " != ") \ 53 << "\"" << s2 << "\"" 54 55#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true) 56#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false) 57 58#define CHECK_PTHREAD_CALL(call, args, what) \ 59 do { \ 60 int rc = call args; \ 61 if (rc != 0) { \ 62 errno = rc; \ 63 PLOG(FATAL) << # call << " failed for " << what; \ 64 } \ 65 } while (false) 66 67#ifndef NDEBUG 68 69#define DCHECK(x) CHECK(x) 70#define DCHECK_EQ(x, y) CHECK_EQ(x, y) 71#define DCHECK_NE(x, y) CHECK_NE(x, y) 72#define DCHECK_LE(x, y) CHECK_LE(x, y) 73#define DCHECK_LT(x, y) CHECK_LT(x, y) 74#define DCHECK_GE(x, y) CHECK_GE(x, y) 75#define DCHECK_GT(x, y) CHECK_GT(x, y) 76#define DCHECK_STREQ(s1, s2) CHECK_STREQ(s1, s2) 77#define DCHECK_STRNE(s1, s2) CHECK_STRNE(s1, s2) 78 79#else // NDEBUG 80 81#define DCHECK(condition) \ 82 while (false) \ 83 CHECK(condition) 84 85#define DCHECK_EQ(val1, val2) \ 86 while (false) \ 87 CHECK_EQ(val1, val2) 88 89#define DCHECK_NE(val1, val2) \ 90 while (false) \ 91 CHECK_NE(val1, val2) 92 93#define DCHECK_LE(val1, val2) \ 94 while (false) \ 95 CHECK_LE(val1, val2) 96 97#define DCHECK_LT(val1, val2) \ 98 while (false) \ 99 CHECK_LT(val1, val2) 100 101#define DCHECK_GE(val1, val2) \ 102 while (false) \ 103 CHECK_GE(val1, val2) 104 105#define DCHECK_GT(val1, val2) \ 106 while (false) \ 107 CHECK_GT(val1, val2) 108 109#define DCHECK_STREQ(str1, str2) \ 110 while (false) \ 111 CHECK_STREQ(str1, str2) 112 113#define DCHECK_STRNE(str1, str2) \ 114 while (false) \ 115 CHECK_STRNE(str1, str2) 116 117#endif 118 119#define LOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, -1).stream() 120#define PLOG(severity) ::art::LogMessage(__FILE__, __LINE__, severity, errno).stream() 121 122#define LG LOG(INFO) 123 124#define UNIMPLEMENTED(level) LOG(level) << __PRETTY_FUNCTION__ << " unimplemented " 125 126#define VLOG_IS_ON(module) UNLIKELY(::art::gLogVerbosity.module) 127#define VLOG(module) if (VLOG_IS_ON(module)) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream() 128#define VLOG_STREAM(module) ::art::LogMessage(__FILE__, __LINE__, INFO, -1).stream() 129 130// 131// Implementation details beyond this point. 132// 133 134namespace art { 135 136template <typename LHS, typename RHS> 137struct EagerEvaluator { 138 EagerEvaluator(LHS lhs, RHS rhs) : lhs(lhs), rhs(rhs) { } 139 LHS lhs; 140 RHS rhs; 141}; 142 143// We want char*s to be treated as pointers, not strings. If you want them treated like strings, 144// you'd need to use CHECK_STREQ and CHECK_STRNE anyway to compare the characters rather than their 145// addresses. We could express this more succinctly with std::remove_const, but this is quick and 146// easy to understand, and works before we have C++0x. We rely on signed/unsigned warnings to 147// protect you against combinations not explicitly listed below. 148#define EAGER_PTR_EVALUATOR(T1, T2) \ 149 template <> struct EagerEvaluator<T1, T2> { \ 150 EagerEvaluator(T1 lhs, T2 rhs) \ 151 : lhs(reinterpret_cast<const void*>(lhs)), \ 152 rhs(reinterpret_cast<const void*>(rhs)) { } \ 153 const void* lhs; \ 154 const void* rhs; \ 155 } 156EAGER_PTR_EVALUATOR(const char*, const char*); 157EAGER_PTR_EVALUATOR(const char*, char*); 158EAGER_PTR_EVALUATOR(char*, const char*); 159EAGER_PTR_EVALUATOR(char*, char*); 160EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*); 161EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*); 162EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*); 163EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*); 164EAGER_PTR_EVALUATOR(const signed char*, const signed char*); 165EAGER_PTR_EVALUATOR(const signed char*, signed char*); 166EAGER_PTR_EVALUATOR(signed char*, const signed char*); 167EAGER_PTR_EVALUATOR(signed char*, signed char*); 168 169template <typename LHS, typename RHS> 170EagerEvaluator<LHS, RHS> MakeEagerEvaluator(LHS lhs, RHS rhs) { 171 return EagerEvaluator<LHS, RHS>(lhs, rhs); 172} 173 174// This indirection greatly reduces the stack impact of having 175// lots of checks/logging in a function. 176struct LogMessageData { 177 public: 178 LogMessageData(const char* file, int line, LogSeverity severity, int error); 179 std::ostringstream buffer; 180 const char* const file; 181 const int line_number; 182 const LogSeverity severity; 183 const int error; 184 185 private: 186 DISALLOW_COPY_AND_ASSIGN(LogMessageData); 187}; 188 189class LogMessage { 190 public: 191 LogMessage(const char* file, int line, LogSeverity severity, int error) 192 : data_(new LogMessageData(file, line, severity, error)) { 193 } 194 195 ~LogMessage() LOCKS_EXCLUDED(Locks::logging_lock_); 196 197 std::ostream& stream() { 198 return data_->buffer; 199 } 200 201 private: 202 static void LogLine(const LogMessageData& data, const char*); 203 204 const UniquePtr<LogMessageData> data_; 205 206 friend void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context); 207 friend class Mutex; 208 DISALLOW_COPY_AND_ASSIGN(LogMessage); 209}; 210 211// A convenience to allow any class with a "Dump(std::ostream& os)" member function 212// but without an operator<< to be used as if it had an operator<<. Use like this: 213// 214// os << Dumpable<MyType>(my_type_instance); 215// 216template<typename T> 217class Dumpable { 218 public: 219 explicit Dumpable(T& value) : value_(value) { 220 } 221 222 void Dump(std::ostream& os) const { 223 value_.Dump(os); 224 } 225 226 private: 227 T& value_; 228 229 DISALLOW_COPY_AND_ASSIGN(Dumpable); 230}; 231 232template<typename T> 233std::ostream& operator<<(std::ostream& os, const Dumpable<T>& rhs) { 234 rhs.Dump(os); 235 return os; 236} 237 238template<typename T> 239class MutatorLockedDumpable { 240 public: 241 explicit MutatorLockedDumpable(T& value) 242 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : value_(value) { 243 } 244 245 void Dump(std::ostream& os) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 246 value_.Dump(os); 247 } 248 249 private: 250 T& value_; 251 252 DISALLOW_COPY_AND_ASSIGN(MutatorLockedDumpable); 253}; 254 255template<typename T> 256std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs) 257// TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) however annotalysis 258// currently fails for this. 259 NO_THREAD_SAFETY_ANALYSIS { 260 rhs.Dump(os); 261 return os; 262} 263 264// Helps you use operator<< in a const char*-like context such as our various 'F' methods with 265// format strings. 266template<typename T> 267class ToStr { 268 public: 269 explicit ToStr(const T& value) { 270 std::ostringstream os; 271 os << value; 272 s_ = os.str(); 273 } 274 275 const char* c_str() const { 276 return s_.c_str(); 277 } 278 279 const std::string& str() const { 280 return s_; 281 } 282 283 private: 284 std::string s_; 285 DISALLOW_COPY_AND_ASSIGN(ToStr); 286}; 287 288// The members of this struct are the valid arguments to VLOG and VLOG_IS_ON in code, 289// and the "-verbose:" command line argument. 290struct LogVerbosity { 291 bool class_linker; // Enabled with "-verbose:class". 292 bool verifier; 293 bool compiler; 294 bool heap; 295 bool gc; 296 bool jdwp; 297 bool jni; 298 bool monitor; 299 bool startup; 300 bool third_party_jni; // Enabled with "-verbose:third-party-jni". 301 bool threads; 302}; 303 304extern LogVerbosity gLogVerbosity; 305 306// Used on fatal exit. Prevents recursive aborts. Allows us to disable 307// some error checking to ensure fatal shutdown makes forward progress. 308extern unsigned int gAborting; 309 310extern void InitLogging(char* argv[]); 311 312extern const char* GetCmdLine(); 313extern const char* ProgramInvocationName(); 314extern const char* ProgramInvocationShortName(); 315 316} // namespace art 317 318#endif // ART_RUNTIME_BASE_LOGGING_H_ 319