src/share/vm/utilities/events.cpp

Sun, 25 Sep 2011 16:03:29 -0700

author
never
date
Sun, 25 Sep 2011 16:03:29 -0700
changeset 3156
f08d439fab8c
parent 2314
f95d63e2154a
child 3499
aa3d708d67c4
permissions
-rw-r--r--

7089790: integrate bsd-port changes
Reviewed-by: kvn, twisti, jrose
Contributed-by: Kurt Miller <kurt@intricatesoftware.com>, Greg Lewis <glewis@eyesbeyond.com>, Jung-uk Kim <jkim@freebsd.org>, Christos Zoulas <christos@zoulas.com>, Landon Fuller <landonf@plausible.coop>, The FreeBSD Foundation <board@freebsdfoundation.org>, Michael Franz <mvfranz@gmail.com>, Roger Hoover <rhoover@apple.com>, Alexander Strange <astrange@apple.com>

     1 /*
     2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     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
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "memory/allocation.inline.hpp"
    27 #include "runtime/mutexLocker.hpp"
    28 #include "runtime/osThread.hpp"
    29 #include "runtime/threadLocalStorage.hpp"
    30 #include "runtime/timer.hpp"
    31 #include "utilities/events.hpp"
    32 #ifdef TARGET_OS_FAMILY_linux
    33 # include "thread_linux.inline.hpp"
    34 #endif
    35 #ifdef TARGET_OS_FAMILY_solaris
    36 # include "thread_solaris.inline.hpp"
    37 #endif
    38 #ifdef TARGET_OS_FAMILY_windows
    39 # include "thread_windows.inline.hpp"
    40 #endif
    41 #ifdef TARGET_OS_FAMILY_bsd
    42 # include "thread_bsd.inline.hpp"
    43 #endif
    46 #ifndef PRODUCT
    48 ////////////////////////////////////////////////////////////////////////////
    49 // Event
    51 typedef u4 EventID;
    53 class Event VALUE_OBJ_CLASS_SPEC  {
    54  private:
    55   jlong       _time_tick;
    56   intx        _thread_id;
    57   const char* _format;
    58   int         _indent;
    59   intptr_t    _arg_1;
    60   intptr_t    _arg_2;
    61   intptr_t    _arg_3;
    63   // only EventBuffer::add_event() can assign event id
    64   friend class EventBuffer;
    65   EventID     _id;
    67  public:
    69   void clear() { _format = NULL; }
    71   EventID id() const { return _id; }
    73   void fill(int indent, const char* format, intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
    74     _format = format;
    75     _arg_1  = arg_1;
    76     _arg_2  = arg_2;
    77     _arg_3  = arg_3;
    79     _indent = indent;
    81     _thread_id = os::current_thread_id();
    82     _time_tick = os::elapsed_counter();
    83   }
    85   void print_on(outputStream *st) {
    86     if (_format == NULL) return;
    87     st->print("  %d", _thread_id);
    88     st->print("  %3.2g   ", (double)_time_tick / os::elapsed_frequency());
    89     st->fill_to(20);
    90     for (int index = 0; index < _indent; index++) {
    91       st->print("| ");
    92     }
    93     st->print_cr(_format, _arg_1, _arg_2, _arg_3);
    94   }
    95 };
    97 ////////////////////////////////////////////////////////////////////////////
    98 // EventBuffer
    99 //
   100 // Simple lock-free event queue. Every event has a unique 32-bit id.
   101 // It's fine if two threads add events at the same time, because they
   102 // will get different event id, and then write to different buffer location.
   103 // However, it is assumed that add_event() is quick enough (or buffer size
   104 // is big enough), so when one thread is adding event, there can't be more
   105 // than "size" events created by other threads; otherwise we'll end up having
   106 // two threads writing to the same location.
   108 class EventBuffer : AllStatic {
   109  private:
   110   static Event* buffer;
   111   static int    size;
   112   static jint   indent;
   113   static volatile EventID _current_event_id;
   115   static EventID get_next_event_id() {
   116     return (EventID)Atomic::add(1, (jint*)&_current_event_id);
   117   }
   119  public:
   120   static void inc_indent() { Atomic::inc(&indent); }
   121   static void dec_indent() { Atomic::dec(&indent); }
   123   static bool get_event(EventID id, Event* event) {
   124     int index = (int)(id % size);
   125     if (buffer[index].id() == id) {
   126       memcpy(event, &buffer[index], sizeof(Event));
   127       // check id again; if buffer[index] is being updated by another thread,
   128       // event->id() will contain different value.
   129       return (event->id() == id);
   130     } else {
   131       // id does not match - id is invalid, or event is overwritten
   132       return false;
   133     }
   134   }
   136   // add a new event to the queue; if EventBuffer is full, this call will
   137   // overwrite the oldest event in the queue
   138   static EventID add_event(const char* format,
   139                            intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
   140     // assign a unique id
   141     EventID id = get_next_event_id();
   143     // event will be copied to buffer[index]
   144     int index = (int)(id % size);
   146     // first, invalidate id, buffer[index] can't have event with id = index + 2
   147     buffer[index]._id = index + 2;
   149     // make sure everyone has seen that buffer[index] is invalid
   150     OrderAccess::fence();
   152     // ... before updating its value
   153     buffer[index].fill(indent, format, arg_1, arg_2, arg_3);
   155     // finally, set up real event id, now buffer[index] contains valid event
   156     OrderAccess::release_store(&(buffer[index]._id), id);
   158     return id;
   159   }
   161   static void print_last(outputStream *st, int number) {
   162     st->print_cr("[Last %d events in the event buffer]", number);
   163     st->print_cr("-<thd>-<elapsed sec>-<description>---------------------");
   165     int count = 0;
   166     EventID id = _current_event_id;
   167     while (count < number) {
   168       Event event;
   169       if (get_event(id, &event)) {
   170          event.print_on(st);
   171       }
   172       id--;
   173       count++;
   174     }
   175   }
   177   static void print_all(outputStream* st) {
   178     print_last(st, size);
   179   }
   181   static void init() {
   182     // Allocate the event buffer
   183     size   = EventLogLength;
   184     buffer = NEW_C_HEAP_ARRAY(Event, size);
   186     _current_event_id = 0;
   188     // Clear the event buffer
   189     for (int index = 0; index < size; index++) {
   190       buffer[index]._id = index + 1;       // index + 1 is invalid id
   191       buffer[index].clear();
   192     }
   193   }
   194 };
   196 Event*           EventBuffer::buffer;
   197 int              EventBuffer::size;
   198 volatile EventID EventBuffer::_current_event_id;
   199 int              EventBuffer::indent;
   201 ////////////////////////////////////////////////////////////////////////////
   202 // Events
   204 // Events::log() is safe for signal handlers
   205 void Events::log(const char* format, ...) {
   206   if (LogEvents) {
   207     va_list ap;
   208     va_start(ap, format);
   209     intptr_t arg_1 = va_arg(ap, intptr_t);
   210     intptr_t arg_2 = va_arg(ap, intptr_t);
   211     intptr_t arg_3 = va_arg(ap, intptr_t);
   212     va_end(ap);
   214     EventBuffer::add_event(format, arg_1, arg_2, arg_3);
   215   }
   216 }
   218 void Events::print_all(outputStream *st) {
   219   EventBuffer::print_all(st);
   220 }
   222 void Events::print_last(outputStream *st, int number) {
   223   EventBuffer::print_last(st, number);
   224 }
   226 ///////////////////////////////////////////////////////////////////////////
   227 // EventMark
   229 EventMark::EventMark(const char* format, ...) {
   230   if (LogEvents) {
   231     va_list ap;
   232     va_start(ap, format);
   233     intptr_t arg_1 = va_arg(ap, intptr_t);
   234     intptr_t arg_2 = va_arg(ap, intptr_t);
   235     intptr_t arg_3 = va_arg(ap, intptr_t);
   236     va_end(ap);
   238     EventBuffer::add_event(format, arg_1, arg_2, arg_3);
   239     EventBuffer::inc_indent();
   240   }
   241 }
   243 EventMark::~EventMark() {
   244   if (LogEvents) {
   245     EventBuffer::dec_indent();
   246     EventBuffer::add_event("done", 0, 0, 0);
   247   }
   248 }
   250 ///////////////////////////////////////////////////////////////////////////
   252 void eventlog_init() {
   253   EventBuffer::init();
   254 }
   256 int print_all_events(outputStream *st) {
   257   EventBuffer::print_all(st);
   258   return 1;
   259 }
   261 #else
   263 void eventlog_init() {}
   264 int print_all_events(outputStream *st) { return 0; }
   266 #endif // PRODUCT

mercurial