events.hpp revision 3863
0N/A/*
1472N/A * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
1879N/A#ifndef SHARE_VM_UTILITIES_EVENTS_HPP
1879N/A#define SHARE_VM_UTILITIES_EVENTS_HPP
1879N/A
1879N/A#include "memory/allocation.hpp"
1879N/A#include "runtime/mutexLocker.hpp"
1879N/A#include "runtime/thread.hpp"
1879N/A#include "utilities/top.hpp"
1879N/A#include "utilities/vmError.hpp"
1879N/A
1879N/A// Events and EventMark provide interfaces to log events taking place in the vm.
0N/A// This facility is extremly useful for post-mortem debugging. The eventlog
0N/A// often provides crucial information about events leading up to the crash.
0N/A//
0N/A// Abstractly the logs can record whatever they way but normally they
0N/A// would record at least a timestamp and the current Thread, along
0N/A// with whatever data they need in a ring buffer. Commonly fixed
0N/A// length text messages are recorded for simplicity but other
0N/A// strategies could be used. Several logs are provided by default but
0N/A// new instances can be created as needed.
1387N/A
0N/A// The base event log dumping class that is registered for dumping at
0N/A// crash time. This is a very generic interface that is mainly here
0N/A// for completeness. Normally the templated EventLogBase would be
0N/A// subclassed to provide different log types.
0N/Aclass EventLog : public CHeapObj<mtInternal> {
0N/A friend class Events;
0N/A
0N/A private:
0N/A EventLog* _next;
0N/A
0N/A EventLog* next() const { return _next; }
542N/A
0N/A public:
0N/A // Automatically registers the log so that it will be printed during
0N/A // crashes.
0N/A EventLog();
0N/A
481N/A virtual void print_log_on(outputStream* out) = 0;
481N/A};
481N/A
1166N/A
1166N/A// A templated subclass of EventLog that provides basic ring buffer
1166N/A// functionality. Most event loggers should subclass this, possibly
0N/A// providing a more featureful log function if the existing copy
0N/A// semantics aren't appropriate. The name is used as the label of the
0N/A// log when it is dumped during a crash.
0N/Atemplate <class T> class EventLogBase : public EventLog {
1753N/A template <class X> class EventRecord {
1753N/A public:
0N/A double timestamp;
0N/A Thread* thread;
0N/A X data;
0N/A };
0N/A
0N/A protected:
0N/A Mutex _mutex;
0N/A const char* _name;
0N/A int _length;
0N/A int _index;
0N/A int _count;
0N/A EventRecord<T>* _records;
0N/A
0N/A public:
0N/A EventLogBase<T>(const char* name, int length = LogEventsBufferEntries):
1166N/A _name(name),
1166N/A _length(length),
1166N/A _count(0),
1166N/A _index(0),
1166N/A _mutex(Mutex::event, name) {
1166N/A _records = new EventRecord<T>[length];
1166N/A }
0N/A
0N/A double fetch_timestamp() {
0N/A return os::elapsedTime();
0N/A }
0N/A
0N/A // move the ring buffer to next open slot and return the index of
0N/A // the slot to use for the current message. Should only be called
0N/A // while mutex is held.
0N/A int compute_log_index() {
0N/A int index = _index;
0N/A if (_count < _length) _count++;
0N/A _index++;
0N/A if (_index >= _length) _index = 0;
0N/A return index;
0N/A }
0N/A
0N/A bool should_log() {
0N/A // Don't bother adding new entries when we're crashing. This also
0N/A // avoids mutating the ring buffer when printing the log.
0N/A return !VMError::fatal_error_in_progress();
0N/A }
0N/A
0N/A // Print the contents of the log
0N/A void print_log_on(outputStream* out);
0N/A
0N/A private:
0N/A void print_log_impl(outputStream* out);
0N/A
0N/A // Print a single element. A templated implementation might need to
0N/A // be declared by subclasses.
0N/A void print(outputStream* out, T& e);
0N/A
0N/A void print(outputStream* out, EventRecord<T>& e) {
0N/A out->print("Event: %.3f ", e.timestamp);
0N/A if (e.thread != NULL) {
0N/A out->print("Thread " INTPTR_FORMAT " ", e.thread);
0N/A }
0N/A print(out, e.data);
0N/A }
0N/A};
0N/A
0N/A// A simple wrapper class for fixed size text messages.
0N/Aclass StringLogMessage : public FormatBuffer<132> {
0N/A public:
0N/A // Wrap this buffer in a stringStream.
0N/A stringStream stream() {
0N/A return stringStream(_buf, sizeof(_buf));
481N/A }
481N/A};
481N/A
481N/A// A simple ring buffer of fixed size text messages.
481N/Aclass StringEventLog : public EventLogBase<StringLogMessage> {
481N/A public:
1165N/A StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase<StringLogMessage>(name, count) {}
481N/A
481N/A void logv(Thread* thread, const char* format, va_list ap) {
481N/A if (!should_log()) return;
1165N/A
481N/A double timestamp = fetch_timestamp();
481N/A MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
1165N/A int index = compute_log_index();
481N/A _records[index].thread = thread;
0N/A _records[index].timestamp = timestamp;
0N/A _records[index].data.printv(format, ap);
0N/A }
0N/A
0N/A void log(Thread* thread, const char* format, ...) {
542N/A va_list ap;
0N/A va_start(ap, format);
0N/A logv(thread, format, ap);
0N/A va_end(ap);
0N/A }
0N/A
0N/A};
0N/A
0N/A
0N/A
0N/Aclass Events : AllStatic {
0N/A friend class EventLog;
0N/A
0N/A private:
0N/A static EventLog* _logs;
0N/A
0N/A // A log for generic messages that aren't well categorized.
0N/A static StringEventLog* _messages;
0N/A
0N/A // A log for internal exception related messages, like internal
0N/A // throws and implicit exceptions.
0N/A static StringEventLog* _exceptions;
0N/A
0N/A // Deoptization related messages
0N/A static StringEventLog* _deopt_messages;
113N/A
0N/A public:
0N/A static void print_all(outputStream* out);
0N/A
0N/A // Dump all events to the tty
0N/A static void print();
0N/A
0N/A // Logs a generic message with timestamp and format as printf.
0N/A static void log(Thread* thread, const char* format, ...);
0N/A
0N/A // Log exception related message
0N/A static void log_exception(Thread* thread, const char* format, ...);
0N/A
0N/A static void log_deopt_message(Thread* thread, const char* format, ...);
0N/A
0N/A // Register default loggers
0N/A static void init();
0N/A};
0N/A
0N/A
0N/Ainline void Events::log(Thread* thread, const char* format, ...) {
0N/A if (LogEvents) {
0N/A va_list ap;
0N/A va_start(ap, format);
0N/A _messages->logv(thread, format, ap);
0N/A va_end(ap);
0N/A }
0N/A}
0N/A
0N/Ainline void Events::log_exception(Thread* thread, const char* format, ...) {
0N/A if (LogEvents) {
0N/A va_list ap;
0N/A va_start(ap, format);
0N/A _exceptions->logv(thread, format, ap);
0N/A va_end(ap);
0N/A }
0N/A}
0N/A
0N/Ainline void Events::log_deopt_message(Thread* thread, const char* format, ...) {
0N/A if (LogEvents) {
0N/A va_list ap;
0N/A va_start(ap, format);
0N/A _deopt_messages->logv(thread, format, ap);
0N/A va_end(ap);
0N/A }
0N/A}
0N/A
0N/A
0N/Atemplate <class T>
0N/Ainline void EventLogBase<T>::print_log_on(outputStream* out) {
0N/A if (ThreadLocalStorage::get_thread_slow() == NULL) {
0N/A // Not a regular Java thread so don't bother locking
0N/A print_log_impl(out);
0N/A } else {
0N/A MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);
0N/A print_log_impl(out);
0N/A }
0N/A}
0N/A
0N/A// Dump the ring buffer entries that current have entries.
0N/Atemplate <class T>
0N/Ainline void EventLogBase<T>::print_log_impl(outputStream* out) {
0N/A out->print_cr("%s (%d events):", _name, _count);
0N/A if (_count == 0) {
0N/A out->print_cr("No events");
0N/A out->cr();
0N/A return;
0N/A }
0N/A
0N/A if (_count < _length) {
0N/A for (int i = 0; i < _count; i++) {
0N/A print(out, _records[i]);
0N/A }
941N/A } else {
941N/A for (int i = _index; i < _length; i++) {
941N/A print(out, _records[i]);
0N/A }
0N/A for (int i = 0; i < _index; i++) {
0N/A print(out, _records[i]);
0N/A }
0N/A }
0N/A out->cr();
0N/A}
0N/A
2474N/A// Implement a printing routine for the StringLogMessage
2474N/Atemplate <>
2474N/Ainline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) {
2474N/A out->print_raw(lm);
2474N/A out->cr();
2474N/A}
2474N/A
941N/A// Place markers for the beginning and end up of a set of events.
941N/A// These end up in the default log.
941N/Aclass EventMark : public StackObj {
941N/A StringLogMessage _buffer;
0N/A
0N/A public:
0N/A // log a begin event, format as printf
0N/A EventMark(const char* format, ...);
0N/A // log an end event
941N/A ~EventMark();
941N/A};
0N/A
0N/A#endif // SHARE_VM_UTILITIES_EVENTS_HPP
989N/A