events.hpp revision 3064:aa3d708d67c4
1/*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#ifndef SHARE_VM_UTILITIES_EVENTS_HPP
26#define SHARE_VM_UTILITIES_EVENTS_HPP
27
28#include "memory/allocation.hpp"
29#include "runtime/mutexLocker.hpp"
30#include "runtime/thread.hpp"
31#include "utilities/top.hpp"
32#include "utilities/vmError.hpp"
33
34// Events and EventMark provide interfaces to log events taking place in the vm.
35// This facility is extremly useful for post-mortem debugging. The eventlog
36// often provides crucial information about events leading up to the crash.
37//
38// All arguments past the format string must be passed as an intptr_t.
39//
40// To log a single event use:
41//    Events::log("New nmethod has been created " INTPTR_FORMAT, nm);
42//
43// To log a block of events use:
44//    EventMark m("GarbageCollecting %d", (intptr_t)gc_number);
45//
46// The constructor to eventlog indents the eventlog until the
47// destructor has been executed.
48//
49// IMPLEMENTATION RESTRICTION:
50//   Max 3 arguments are saved for each logged event.
51//
52
53// The base event log dumping class that is registered for dumping at
54// crash time.  This is a very generic interface that is mainly here
55// for completeness.  Normally the templated EventLogBase would be
56// subclassed to provide different log types.
57class EventLog : public CHeapObj {
58  friend class Events;
59
60 private:
61  EventLog* _next;
62
63  EventLog* next() const { return _next; }
64
65 public:
66  // Automatically registers the log so that it will be printed during
67  // crashes.
68  EventLog();
69
70  virtual void print_log_on(outputStream* out) = 0;
71};
72
73
74// A templated subclass of EventLog that provides basic ring buffer
75// functionality.  Most event loggers should subclass this, possibly
76// providing a more featureful log function if the existing copy
77// semantics aren't appropriate.  The name is used as the label of the
78// log when it is dumped during a crash.
79template <class T> class EventLogBase : public EventLog {
80  template <class X> class EventRecord {
81   public:
82    jlong   timestamp;
83    Thread* thread;
84    X       data;
85  };
86
87 protected:
88  Mutex           _mutex;
89  const char*     _name;
90  int             _length;
91  int             _index;
92  int             _count;
93  EventRecord<T>* _records;
94
95 public:
96  EventLogBase<T>(const char* name, int length = LogEventsBufferEntries):
97    _name(name),
98    _length(length),
99    _count(0),
100    _index(0),
101    _mutex(Mutex::event, name) {
102    _records = new EventRecord<T>[length];
103  }
104
105  // move the ring buffer to next open slot and return the index of
106  // the slot to use for the current message.  Should only be called
107  // while mutex is held.
108  int compute_log_index() {
109    int index = _index;
110    if (_count < _length) _count++;
111    _index++;
112    if (_index >= _length) _index = 0;
113    return index;
114  }
115
116  bool should_log() {
117    // Don't bother adding new entries when we're crashing.  This also
118    // avoids mutating the ring buffer when printing the log.
119    return !VMError::fatal_error_in_progress();
120  }
121
122  // Print the contents of the log
123  void print_log_on(outputStream* out);
124
125 private:
126  void print_log_impl(outputStream* out);
127
128  // Print a single element.  A templated implementation might need to
129  // be declared by subclasses.
130  void print(outputStream* out, T& e);
131
132  void print(outputStream* out, EventRecord<T>& e) {
133    out->print("Event: " INT64_FORMAT " ", e.timestamp);
134    if (e.thread != NULL) {
135      out->print("Thread " INTPTR_FORMAT " ", e.thread);
136    }
137    print(out, e.data);
138  }
139};
140
141// A simple wrapper class for fixed size text messages.
142class StringLogMessage : public FormatBuffer<132> {
143 public:
144  // Wrap this buffer in a stringStream.
145  stringStream stream() {
146    return stringStream(_buf, sizeof(_buf));
147  }
148};
149
150// A simple ring buffer of fixed size text messages.
151class StringEventLog : public EventLogBase<StringLogMessage> {
152 public:
153  StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase<StringLogMessage>(name, count) {}
154
155  void logv(Thread* thread, const char* format, va_list ap) {
156    if (!should_log()) return;
157
158    jlong timestamp = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
159    MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
160    int index = compute_log_index();
161    _records[index].thread = thread;
162    _records[index].timestamp = timestamp;
163    _records[index].data.printv(format, ap);
164  }
165
166  void log(Thread* thread, const char* format, ...) {
167    va_list ap;
168    va_start(ap, format);
169    logv(thread, format, ap);
170    va_end(ap);
171  }
172
173};
174
175
176
177class Events : AllStatic {
178  friend class EventLog;
179
180 private:
181  static EventLog* _logs;
182
183  // A log for generic messages that aren't well categorized.
184  static StringEventLog* _messages;
185
186  // A log for internal exception related messages, like internal
187  // throws and implicit exceptions.
188  static StringEventLog* _exceptions;
189
190  // Deoptization related messages
191  static StringEventLog* _deopt_messages;
192
193 public:
194  static void print_all(outputStream* out);
195
196  static void print() {
197    print_all(tty);
198  }
199
200  // Logs a generic message with timestamp and format as printf.
201  static void log(Thread* thread, const char* format, ...);
202
203  // Log exception related message
204  static void log_exception(Thread* thread, const char* format, ...);
205
206  static void log_deopt_message(Thread* thread, const char* format, ...);
207
208  // Register default loggers
209  static void init();
210};
211
212
213inline void Events::log(Thread* thread, const char* format, ...) {
214  if (LogEvents) {
215    va_list ap;
216    va_start(ap, format);
217    _messages->logv(thread, format, ap);
218    va_end(ap);
219  }
220}
221
222inline void Events::log_exception(Thread* thread, const char* format, ...) {
223  if (LogEvents) {
224    va_list ap;
225    va_start(ap, format);
226    _exceptions->logv(thread, format, ap);
227    va_end(ap);
228  }
229}
230
231inline void Events::log_deopt_message(Thread* thread, const char* format, ...) {
232  if (LogEvents) {
233    va_list ap;
234    va_start(ap, format);
235    _deopt_messages->logv(thread, format, ap);
236    va_end(ap);
237  }
238}
239
240
241template <class T>
242inline void EventLogBase<T>::print_log_on(outputStream* out) {
243  if (ThreadLocalStorage::get_thread_slow() == NULL) {
244    // Not a regular Java thread so don't bother locking
245    print_log_impl(out);
246  } else {
247    MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
248    print_log_impl(out);
249  }
250}
251
252// Dump the ring buffer entries that current have entries.
253template <class T>
254inline void EventLogBase<T>::print_log_impl(outputStream* out) {
255  out->print_cr("%s (%d events):", _name, _count);
256  if (_count == 0) {
257    out->print_cr("No events");
258    return;
259  }
260
261  if (_count < _length) {
262    for (int i = 0; i < _count; i++) {
263      print(out, _records[i]);
264    }
265  } else {
266    for (int i = _index; i < _length; i++) {
267      print(out, _records[i]);
268    }
269    for (int i = 0; i < _index; i++) {
270      print(out, _records[i]);
271    }
272  }
273  out->cr();
274}
275
276// Implement a printing routine for the StringLogMessage
277template <>
278inline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) {
279  out->print_raw(lm);
280  out->cr();
281}
282
283// Place markers for the beginning and end up of a set of events.
284// These end up in the default log.
285class EventMark : public StackObj {
286  StringLogMessage _buffer;
287
288 public:
289  // log a begin event, format as printf
290  EventMark(const char* format, ...);
291  // log an end event
292  ~EventMark();
293};
294
295#endif // SHARE_VM_UTILITIES_EVENTS_HPP
296