Path: blob/master/src/hotspot/share/utilities/events.hpp
64440 views
/*1* Copyright (c) 1997, 2020, 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_UTILITIES_EVENTS_HPP25#define SHARE_UTILITIES_EVENTS_HPP2627#include "memory/allocation.hpp"28#include "runtime/mutexLocker.hpp"29#include "runtime/thread.hpp"30#include "utilities/formatBuffer.hpp"31#include "utilities/globalDefinitions.hpp"32#include "utilities/ostream.hpp"33#include "utilities/vmError.hpp"3435// Events and EventMark provide interfaces to log events taking place in the vm.36// This facility is extremly useful for post-mortem debugging. The eventlog37// often provides crucial information about events leading up to the crash.38//39// Abstractly the logs can record whatever they way but normally they40// would record at least a timestamp and the current Thread, along41// with whatever data they need in a ring buffer. Commonly fixed42// length text messages are recorded for simplicity but other43// strategies could be used. Several logs are provided by default but44// new instances can be created as needed.4546// The base event log dumping class that is registered for dumping at47// crash time. This is a very generic interface that is mainly here48// for completeness. Normally the templated EventLogBase would be49// subclassed to provide different log types.50class EventLog : public CHeapObj<mtInternal> {51friend class Events;5253private:54EventLog* _next;5556EventLog* next() const { return _next; }5758public:59// Automatically registers the log so that it will be printed during60// crashes.61EventLog();6263// Print log to output stream.64virtual void print_log_on(outputStream* out, int max = -1) = 0;6566// Returns true if s matches either the log name or the log handle.67virtual bool matches_name_or_handle(const char* s) const = 0;6869// Print log names (for help output of VM.events).70virtual void print_names(outputStream* out) const = 0;7172};737475// A templated subclass of EventLog that provides basic ring buffer76// functionality. Most event loggers should subclass this, possibly77// providing a more featureful log function if the existing copy78// semantics aren't appropriate. The name is used as the label of the79// log when it is dumped during a crash.80template <class T> class EventLogBase : public EventLog {81template <class X> class EventRecord : public CHeapObj<mtInternal> {82public:83double timestamp;84Thread* thread;85X data;86};8788protected:89Mutex _mutex;90// Name is printed out as a header.91const char* _name;92// Handle is a short specifier used to select this particular event log93// for printing (see VM.events command).94const char* _handle;95int _length;96int _index;97int _count;98EventRecord<T>* _records;99100public:101EventLogBase<T>(const char* name, const char* handle, int length = LogEventsBufferEntries):102_mutex(Mutex::event, name, true, Mutex::_safepoint_check_never),103_name(name),104_handle(handle),105_length(length),106_index(0),107_count(0) {108_records = new EventRecord<T>[length];109}110111double fetch_timestamp() {112return os::elapsedTime();113}114115// move the ring buffer to next open slot and return the index of116// the slot to use for the current message. Should only be called117// while mutex is held.118int compute_log_index() {119int index = _index;120if (_count < _length) _count++;121_index++;122if (_index >= _length) _index = 0;123return index;124}125126bool should_log() {127// Don't bother adding new entries when we're crashing. This also128// avoids mutating the ring buffer when printing the log.129return !VMError::is_error_reported();130}131132// Print the contents of the log133void print_log_on(outputStream* out, int max = -1);134135// Returns true if s matches either the log name or the log handle.136bool matches_name_or_handle(const char* s) const;137138// Print log names (for help output of VM.events).139void print_names(outputStream* out) const;140141private:142void print_log_impl(outputStream* out, int max = -1);143144// Print a single element. A templated implementation might need to145// be declared by subclasses.146void print(outputStream* out, T& e);147148void print(outputStream* out, EventRecord<T>& e) {149out->print("Event: %.3f ", e.timestamp);150if (e.thread != NULL) {151out->print("Thread " INTPTR_FORMAT " ", p2i(e.thread));152}153print(out, e.data);154}155};156157// A simple wrapper class for fixed size text messages.158template <size_t bufsz>159class FormatStringLogMessage : public FormatBuffer<bufsz> {160};161typedef FormatStringLogMessage<256> StringLogMessage;162typedef FormatStringLogMessage<512> ExtendedStringLogMessage;163164// A simple ring buffer of fixed size text messages.165template <size_t bufsz>166class FormatStringEventLog : public EventLogBase< FormatStringLogMessage<bufsz> > {167public:168FormatStringEventLog(const char* name, const char* short_name, int count = LogEventsBufferEntries)169: EventLogBase< FormatStringLogMessage<bufsz> >(name, short_name, count) {}170171void logv(Thread* thread, const char* format, va_list ap) ATTRIBUTE_PRINTF(3, 0) {172if (!this->should_log()) return;173174double timestamp = this->fetch_timestamp();175MutexLocker ml(&this->_mutex, Mutex::_no_safepoint_check_flag);176int index = this->compute_log_index();177this->_records[index].thread = thread;178this->_records[index].timestamp = timestamp;179this->_records[index].data.printv(format, ap);180}181182void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(3, 4) {183va_list ap;184va_start(ap, format);185this->logv(thread, format, ap);186va_end(ap);187}188};189typedef FormatStringEventLog<256> StringEventLog;190typedef FormatStringEventLog<512> ExtendedStringEventLog;191192class InstanceKlass;193194// Event log for class unloading events to materialize the class name in place in the log stream.195class UnloadingEventLog : public EventLogBase<StringLogMessage> {196public:197UnloadingEventLog(const char* name, const char* short_name, int count = LogEventsBufferEntries)198: EventLogBase<StringLogMessage>(name, short_name, count) {}199200void log(Thread* thread, InstanceKlass* ik);201};202203// Event log for exceptions204class ExceptionsEventLog : public ExtendedStringEventLog {205public:206ExceptionsEventLog(const char* name, const char* short_name, int count = LogEventsBufferEntries)207: ExtendedStringEventLog(name, short_name, count) {}208209void log(Thread* thread, Handle h_exception, const char* message, const char* file, int line);210};211212213class Events : AllStatic {214friend class EventLog;215216private:217static EventLog* _logs;218219// A log for generic messages that aren't well categorized.220static StringEventLog* _messages;221222// A log for VM Operations223static StringEventLog* _vm_operations;224225// A log for internal exception related messages, like internal226// throws and implicit exceptions.227static ExceptionsEventLog* _exceptions;228229// Deoptization related messages230static StringEventLog* _deopt_messages;231232// dynamic lib related messages233static StringEventLog* _dll_messages;234235// Redefinition related messages236static StringEventLog* _redefinitions;237238// Class unloading events239static UnloadingEventLog* _class_unloading;240public:241242// Print all event logs; limit number of events per event log to be printed with max243// (max == -1 prints all events).244static void print_all(outputStream* out, int max = -1);245246// Print a single event log specified by name or handle.247static void print_one(outputStream* out, const char* log_name, int max = -1);248249// Dump all events to the tty250static void print();251252// Logs a generic message with timestamp and format as printf.253static void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);254255static void log_vm_operation(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);256257// Log exception related message258static void log_exception(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);259static void log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line);260261static void log_redefinition(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);262263static void log_class_unloading(Thread* thread, InstanceKlass* ik);264265static void log_deopt_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);266267static void log_dll_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);268269// Register default loggers270static void init();271};272273inline void Events::log(Thread* thread, const char* format, ...) {274if (LogEvents && _messages != NULL) {275va_list ap;276va_start(ap, format);277_messages->logv(thread, format, ap);278va_end(ap);279}280}281282inline void Events::log_vm_operation(Thread* thread, const char* format, ...) {283if (LogEvents && _vm_operations != NULL) {284va_list ap;285va_start(ap, format);286_vm_operations->logv(thread, format, ap);287va_end(ap);288}289}290291inline void Events::log_exception(Thread* thread, const char* format, ...) {292if (LogEvents && _exceptions != NULL) {293va_list ap;294va_start(ap, format);295_exceptions->logv(thread, format, ap);296va_end(ap);297}298}299300inline void Events::log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line) {301if (LogEvents && _exceptions != NULL) {302_exceptions->log(thread, h_exception, message, file, line);303}304}305306inline void Events::log_redefinition(Thread* thread, const char* format, ...) {307if (LogEvents && _redefinitions != NULL) {308va_list ap;309va_start(ap, format);310_redefinitions->logv(thread, format, ap);311va_end(ap);312}313}314315inline void Events::log_class_unloading(Thread* thread, InstanceKlass* ik) {316if (LogEvents && _class_unloading != NULL) {317_class_unloading->log(thread, ik);318}319}320321inline void Events::log_deopt_message(Thread* thread, const char* format, ...) {322if (LogEvents && _deopt_messages != NULL) {323va_list ap;324va_start(ap, format);325_deopt_messages->logv(thread, format, ap);326va_end(ap);327}328}329330inline void Events::log_dll_message(Thread* thread, const char* format, ...) {331if (LogEvents && _dll_messages != NULL) {332va_list ap;333va_start(ap, format);334_dll_messages->logv(thread, format, ap);335va_end(ap);336}337}338339template <class T>340inline void EventLogBase<T>::print_log_on(outputStream* out, int max) {341struct MaybeLocker {342Mutex* const _mutex;343bool _proceed;344bool _locked;345346MaybeLocker(Mutex* mutex) : _mutex(mutex), _proceed(false), _locked(false) {347if (Thread::current_or_null() == NULL) {348_proceed = true;349} else if (VMError::is_error_reported()) {350if (_mutex->try_lock_without_rank_check()) {351_proceed = _locked = true;352}353} else {354_mutex->lock_without_safepoint_check();355_proceed = _locked = true;356}357}358~MaybeLocker() {359if (_locked) {360_mutex->unlock();361}362}363};364365MaybeLocker ml(&_mutex);366367if (ml._proceed) {368print_log_impl(out, max);369} else {370out->print_cr("%s (%d events):", _name, _count);371out->print_cr("No events printed - crash while holding lock");372out->cr();373}374}375376template <class T>377inline bool EventLogBase<T>::matches_name_or_handle(const char* s) const {378return ::strcasecmp(s, _name) == 0 ||379::strcasecmp(s, _handle) == 0;380}381382template <class T>383inline void EventLogBase<T>::print_names(outputStream* out) const {384out->print("\"%s\" : %s", _handle, _name);385}386387// Dump the ring buffer entries that current have entries.388template <class T>389inline void EventLogBase<T>::print_log_impl(outputStream* out, int max) {390out->print_cr("%s (%d events):", _name, _count);391if (_count == 0) {392out->print_cr("No events");393out->cr();394return;395}396397int printed = 0;398if (_count < _length) {399for (int i = 0; i < _count; i++) {400if (max > 0 && printed == max) {401break;402}403print(out, _records[i]);404printed ++;405}406} else {407for (int i = _index; i < _length; i++) {408if (max > 0 && printed == max) {409break;410}411print(out, _records[i]);412printed ++;413}414for (int i = 0; i < _index; i++) {415if (max > 0 && printed == max) {416break;417}418print(out, _records[i]);419printed ++;420}421}422423if (printed == max) {424out->print_cr("...(skipped)");425}426427out->cr();428}429430// Implement a printing routine for the StringLogMessage431template <>432inline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) {433out->print_raw(lm);434out->cr();435}436437// Implement a printing routine for the ExtendedStringLogMessage438template <>439inline void EventLogBase<ExtendedStringLogMessage>::print(outputStream* out, ExtendedStringLogMessage& lm) {440out->print_raw(lm);441out->cr();442}443444typedef void (*EventLogFunction)(Thread* thread, const char* format, ...);445446class EventMarkBase : public StackObj {447EventLogFunction _log_function;448StringLogMessage _buffer;449450NONCOPYABLE(EventMarkBase);451452protected:453void log_start(const char* format, va_list argp) ATTRIBUTE_PRINTF(2, 0);454void log_end();455456EventMarkBase(EventLogFunction log_function);457};458459// Place markers for the beginning and end up of a set of events.460template <EventLogFunction log_function>461class EventMarkWithLogFunction : public EventMarkBase {462StringLogMessage _buffer;463464public:465// log a begin event, format as printf466EventMarkWithLogFunction(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) :467EventMarkBase(log_function) {468if (LogEvents) {469va_list ap;470va_start(ap, format);471log_start(format, ap);472va_end(ap);473}474}475// log an end event476~EventMarkWithLogFunction() {477if (LogEvents) {478log_end();479}480}481};482483// These end up in the default log.484typedef EventMarkWithLogFunction<Events::log> EventMark;485486// These end up in the vm_operation log.487typedef EventMarkWithLogFunction<Events::log_vm_operation> EventMarkVMOperation;488489#endif // SHARE_UTILITIES_EVENTS_HPP490491492