comparison src/share/vm/utilities/events.hpp @ 4970:33df1aeaebbf

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