Path: blob/master/src/hotspot/share/utilities/events.hpp
40949 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// Redefinition related messages233static StringEventLog* _redefinitions;234235// Class unloading events236static UnloadingEventLog* _class_unloading;237public:238239// Print all event logs; limit number of events per event log to be printed with max240// (max == -1 prints all events).241static void print_all(outputStream* out, int max = -1);242243// Print a single event log specified by name or handle.244static void print_one(outputStream* out, const char* log_name, int max = -1);245246// Dump all events to the tty247static void print();248249// Logs a generic message with timestamp and format as printf.250static void log(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);251252static void log_vm_operation(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);253254// Log exception related message255static void log_exception(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);256static void log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line);257258static void log_redefinition(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);259260static void log_class_unloading(Thread* thread, InstanceKlass* ik);261262static void log_deopt_message(Thread* thread, const char* format, ...) ATTRIBUTE_PRINTF(2, 3);263264// Register default loggers265static void init();266};267268inline void Events::log(Thread* thread, const char* format, ...) {269if (LogEvents && _messages != NULL) {270va_list ap;271va_start(ap, format);272_messages->logv(thread, format, ap);273va_end(ap);274}275}276277inline void Events::log_vm_operation(Thread* thread, const char* format, ...) {278if (LogEvents && _vm_operations != NULL) {279va_list ap;280va_start(ap, format);281_vm_operations->logv(thread, format, ap);282va_end(ap);283}284}285286inline void Events::log_exception(Thread* thread, const char* format, ...) {287if (LogEvents && _exceptions != NULL) {288va_list ap;289va_start(ap, format);290_exceptions->logv(thread, format, ap);291va_end(ap);292}293}294295inline void Events::log_exception(Thread* thread, Handle h_exception, const char* message, const char* file, int line) {296if (LogEvents && _exceptions != NULL) {297_exceptions->log(thread, h_exception, message, file, line);298}299}300301inline void Events::log_redefinition(Thread* thread, const char* format, ...) {302if (LogEvents && _redefinitions != NULL) {303va_list ap;304va_start(ap, format);305_redefinitions->logv(thread, format, ap);306va_end(ap);307}308}309310inline void Events::log_class_unloading(Thread* thread, InstanceKlass* ik) {311if (LogEvents && _class_unloading != NULL) {312_class_unloading->log(thread, ik);313}314}315316inline void Events::log_deopt_message(Thread* thread, const char* format, ...) {317if (LogEvents && _deopt_messages != NULL) {318va_list ap;319va_start(ap, format);320_deopt_messages->logv(thread, format, ap);321va_end(ap);322}323}324325template <class T>326inline void EventLogBase<T>::print_log_on(outputStream* out, int max) {327struct MaybeLocker {328Mutex* const _mutex;329bool _proceed;330bool _locked;331332MaybeLocker(Mutex* mutex) : _mutex(mutex), _proceed(false), _locked(false) {333if (Thread::current_or_null() == NULL) {334_proceed = true;335} else if (VMError::is_error_reported()) {336if (_mutex->try_lock_without_rank_check()) {337_proceed = _locked = true;338}339} else {340_mutex->lock_without_safepoint_check();341_proceed = _locked = true;342}343}344~MaybeLocker() {345if (_locked) {346_mutex->unlock();347}348}349};350351MaybeLocker ml(&_mutex);352353if (ml._proceed) {354print_log_impl(out, max);355} else {356out->print_cr("%s (%d events):", _name, _count);357out->print_cr("No events printed - crash while holding lock");358out->cr();359}360}361362template <class T>363inline bool EventLogBase<T>::matches_name_or_handle(const char* s) const {364return ::strcasecmp(s, _name) == 0 ||365::strcasecmp(s, _handle) == 0;366}367368template <class T>369inline void EventLogBase<T>::print_names(outputStream* out) const {370out->print("\"%s\" : %s", _handle, _name);371}372373// Dump the ring buffer entries that current have entries.374template <class T>375inline void EventLogBase<T>::print_log_impl(outputStream* out, int max) {376out->print_cr("%s (%d events):", _name, _count);377if (_count == 0) {378out->print_cr("No events");379out->cr();380return;381}382383int printed = 0;384if (_count < _length) {385for (int i = 0; i < _count; i++) {386if (max > 0 && printed == max) {387break;388}389print(out, _records[i]);390printed ++;391}392} else {393for (int i = _index; i < _length; i++) {394if (max > 0 && printed == max) {395break;396}397print(out, _records[i]);398printed ++;399}400for (int i = 0; i < _index; i++) {401if (max > 0 && printed == max) {402break;403}404print(out, _records[i]);405printed ++;406}407}408409if (printed == max) {410out->print_cr("...(skipped)");411}412413out->cr();414}415416// Implement a printing routine for the StringLogMessage417template <>418inline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) {419out->print_raw(lm);420out->cr();421}422423// Implement a printing routine for the ExtendedStringLogMessage424template <>425inline void EventLogBase<ExtendedStringLogMessage>::print(outputStream* out, ExtendedStringLogMessage& lm) {426out->print_raw(lm);427out->cr();428}429430typedef void (*EventLogFunction)(Thread* thread, const char* format, ...);431432class EventMarkBase : public StackObj {433EventLogFunction _log_function;434StringLogMessage _buffer;435436NONCOPYABLE(EventMarkBase);437438protected:439void log_start(const char* format, va_list argp) ATTRIBUTE_PRINTF(2, 0);440void log_end();441442EventMarkBase(EventLogFunction log_function);443};444445// Place markers for the beginning and end up of a set of events.446template <EventLogFunction log_function>447class EventMarkWithLogFunction : public EventMarkBase {448StringLogMessage _buffer;449450public:451// log a begin event, format as printf452EventMarkWithLogFunction(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) :453EventMarkBase(log_function) {454if (LogEvents) {455va_list ap;456va_start(ap, format);457log_start(format, ap);458va_end(ap);459}460}461// log an end event462~EventMarkWithLogFunction() {463if (LogEvents) {464log_end();465}466}467};468469// These end up in the default log.470typedef EventMarkWithLogFunction<Events::log> EventMark;471472// These end up in the vm_operation log.473typedef EventMarkWithLogFunction<Events::log_vm_operation> EventMarkVMOperation;474475#endif // SHARE_UTILITIES_EVENTS_HPP476477478