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