Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/utilities/events.hpp
32285 views
/*1* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_UTILITIES_EVENTS_HPP25#define SHARE_VM_UTILITIES_EVENTS_HPP2627#include "memory/allocation.hpp"28#include "runtime/mutexLocker.hpp"29#include "runtime/thread.hpp"30#include "utilities/top.hpp"31#include "utilities/vmError.hpp"3233// Events and EventMark provide interfaces to log events taking place in the vm.34// This facility is extremly useful for post-mortem debugging. The eventlog35// often provides crucial information about events leading up to the crash.36//37// Abstractly the logs can record whatever they way but normally they38// would record at least a timestamp and the current Thread, along39// with whatever data they need in a ring buffer. Commonly fixed40// length text messages are recorded for simplicity but other41// strategies could be used. Several logs are provided by default but42// new instances can be created as needed.4344// The base event log dumping class that is registered for dumping at45// crash time. This is a very generic interface that is mainly here46// for completeness. Normally the templated EventLogBase would be47// subclassed to provide different log types.48class EventLog : public CHeapObj<mtInternal> {49friend class Events;5051private:52EventLog* _next;5354EventLog* next() const { return _next; }5556public:57// Automatically registers the log so that it will be printed during58// crashes.59EventLog();6061virtual void print_log_on(outputStream* out) = 0;62};636465// A templated subclass of EventLog that provides basic ring buffer66// functionality. Most event loggers should subclass this, possibly67// providing a more featureful log function if the existing copy68// semantics aren't appropriate. The name is used as the label of the69// log when it is dumped during a crash.70template <class T> class EventLogBase : public EventLog {71template <class X> class EventRecord : public CHeapObj<mtInternal> {72public:73double timestamp;74Thread* thread;75X data;76};7778protected:79Mutex _mutex;80const char* _name;81int _length;82int _index;83int _count;84EventRecord<T>* _records;8586public:87EventLogBase<T>(const char* name, int length = LogEventsBufferEntries):88_name(name),89_length(length),90_count(0),91_index(0),92_mutex(Mutex::event, name) {93_records = new EventRecord<T>[length];94}9596double fetch_timestamp() {97return os::elapsedTime();98}99100// move the ring buffer to next open slot and return the index of101// the slot to use for the current message. Should only be called102// while mutex is held.103int compute_log_index() {104int index = _index;105if (_count < _length) _count++;106_index++;107if (_index >= _length) _index = 0;108return index;109}110111bool should_log() {112// Don't bother adding new entries when we're crashing. This also113// avoids mutating the ring buffer when printing the log.114return !VMError::fatal_error_in_progress();115}116117// Print the contents of the log118void print_log_on(outputStream* out);119120private:121void print_log_impl(outputStream* out);122123// Print a single element. A templated implementation might need to124// be declared by subclasses.125void print(outputStream* out, T& e);126127void print(outputStream* out, EventRecord<T>& e) {128out->print("Event: %.3f ", e.timestamp);129if (e.thread != NULL) {130out->print("Thread " INTPTR_FORMAT " ", p2i(e.thread));131}132print(out, e.data);133}134};135136// A simple wrapper class for fixed size text messages.137class StringLogMessage : public FormatBuffer<256> {138public:139// Wrap this buffer in a stringStream.140stringStream stream() {141return stringStream(_buf, size());142}143};144145// A simple ring buffer of fixed size text messages.146class StringEventLog : public EventLogBase<StringLogMessage> {147public:148StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase<StringLogMessage>(name, count) {}149150void logv(Thread* thread, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0) {151if (!should_log()) return;152153double timestamp = fetch_timestamp();154MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);155int index = compute_log_index();156_records[index].thread = thread;157_records[index].timestamp = timestamp;158_records[index].data.printv(format, ap);159}160161void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(3, 4) {162va_list ap;163va_start(ap, format);164logv(thread, format, ap);165va_end(ap);166}167168};169170171172class Events : AllStatic {173friend class EventLog;174175private:176static EventLog* _logs;177178// A log for generic messages that aren't well categorized.179static StringEventLog* _messages;180181// A log for internal exception related messages, like internal182// throws and implicit exceptions.183static StringEventLog* _exceptions;184185// Deoptization related messages186static StringEventLog* _deopt_messages;187188// Redefinition related messages189static StringEventLog* _redefinitions;190191public:192static void print_all(outputStream* out);193194// Dump all events to the tty195static void print();196197// Logs a generic message with timestamp and format as printf.198static void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);199200// Log exception related message201static void log_exception(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);202203static void log_redefinition(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);204205static void log_deopt_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);206207// Register default loggers208static void init();209};210211inline void Events::log(Thread* thread, const char* format, ...) {212if (LogEvents) {213va_list ap;214va_start(ap, format);215_messages->logv(thread, format, ap);216va_end(ap);217}218}219220inline void Events::log_exception(Thread* thread, const char* format, ...) {221if (LogEvents) {222va_list ap;223va_start(ap, format);224_exceptions->logv(thread, format, ap);225va_end(ap);226}227}228229inline void Events::log_redefinition(Thread* thread, const char* format, ...) {230if (LogEvents) {231va_list ap;232va_start(ap, format);233_redefinitions->logv(thread, format, ap);234va_end(ap);235}236}237238inline void Events::log_deopt_message(Thread* thread, const char* format, ...) {239if (LogEvents) {240va_list ap;241va_start(ap, format);242_deopt_messages->logv(thread, format, ap);243va_end(ap);244}245}246247248template <class T>249inline void EventLogBase<T>::print_log_on(outputStream* out) {250if (ThreadLocalStorage::get_thread_slow() == NULL) {251// Not a regular Java thread so don't bother locking252print_log_impl(out);253} else {254MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag);255print_log_impl(out);256}257}258259// Dump the ring buffer entries that current have entries.260template <class T>261inline void EventLogBase<T>::print_log_impl(outputStream* out) {262out->print_cr("%s (%d events):", _name, _count);263if (_count == 0) {264out->print_cr("No events");265out->cr();266return;267}268269if (_count < _length) {270for (int i = 0; i < _count; i++) {271print(out, _records[i]);272}273} else {274for (int i = _index; i < _length; i++) {275print(out, _records[i]);276}277for (int i = 0; i < _index; i++) {278print(out, _records[i]);279}280}281out->cr();282}283284// Implement a printing routine for the StringLogMessage285template <>286inline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) {287out->print_raw(lm);288out->cr();289}290291// Place markers for the beginning and end up of a set of events.292// These end up in the default log.293class EventMark : public StackObj {294StringLogMessage _buffer;295296public:297// log a begin event, format as printf298EventMark(const char* format, ...) ATTRIBUTE_PRINTF(2, 3);299// log an end event300~EventMark();301};302303#endif // SHARE_VM_UTILITIES_EVENTS_HPP304305306