1 /*
   2  * Copyright (c) 1997, 2006, 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  */
  24 
  25 #include "incls/_precompiled.incl"
  26 #include "incls/_events.cpp.incl"
  27 
  28 
  29 #ifndef PRODUCT
  30 
  31 ////////////////////////////////////////////////////////////////////////////
  32 // Event
  33 
  34 typedef u4 EventID;
  35 
  36 class Event VALUE_OBJ_CLASS_SPEC  {
  37  private:
  38   jlong       _time_tick;
  39   intx        _thread_id;
  40   const char* _format;
  41   int         _indent;
  42   intptr_t    _arg_1;
  43   intptr_t    _arg_2;
  44   intptr_t    _arg_3;
  45 
  46   // only EventBuffer::add_event() can assign event id
  47   friend class EventBuffer;
  48   EventID     _id;
  49 
  50  public:
  51 
  52   void clear() { _format = NULL; }
  53 
  54   EventID id() const { return _id; }
  55 
  56   void fill(int indent, const char* format, intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
  57     _format = format;
  58     _arg_1  = arg_1;
  59     _arg_2  = arg_2;
  60     _arg_3  = arg_3;
  61 
  62     _indent = indent;
  63 
  64     _thread_id = os::current_thread_id();
  65     _time_tick = os::elapsed_counter();
  66   }
  67 
  68   void print_on(outputStream *st) {
  69     if (_format == NULL) return;
  70     st->print("  %d", _thread_id);
  71     st->print("  %3.2g   ", (double)_time_tick / os::elapsed_frequency());
  72     st->fill_to(20);
  73     for (int index = 0; index < _indent; index++) {
  74       st->print("| ");
  75     }
  76     st->print_cr(_format, _arg_1, _arg_2, _arg_3);
  77   }
  78 };
  79 
  80 ////////////////////////////////////////////////////////////////////////////
  81 // EventBuffer
  82 //
  83 // Simple lock-free event queue. Every event has a unique 32-bit id.
  84 // It's fine if two threads add events at the same time, because they
  85 // will get different event id, and then write to different buffer location.
  86 // However, it is assumed that add_event() is quick enough (or buffer size
  87 // is big enough), so when one thread is adding event, there can't be more
  88 // than "size" events created by other threads; otherwise we'll end up having
  89 // two threads writing to the same location.
  90 
  91 class EventBuffer : AllStatic {
  92  private:
  93   static Event* buffer;
  94   static int    size;
  95   static jint   indent;
  96   static volatile EventID _current_event_id;
  97 
  98   static EventID get_next_event_id() {
  99     return (EventID)Atomic::add(1, (jint*)&_current_event_id);
 100   }
 101 
 102  public:
 103   static void inc_indent() { Atomic::inc(&indent); }
 104   static void dec_indent() { Atomic::dec(&indent); }
 105 
 106   static bool get_event(EventID id, Event* event) {
 107     int index = (int)(id % size);
 108     if (buffer[index].id() == id) {
 109       memcpy(event, &buffer[index], sizeof(Event));
 110       // check id again; if buffer[index] is being updated by another thread,
 111       // event->id() will contain different value.
 112       return (event->id() == id);
 113     } else {
 114       // id does not match - id is invalid, or event is overwritten
 115       return false;
 116     }
 117   }
 118 
 119   // add a new event to the queue; if EventBuffer is full, this call will
 120   // overwrite the oldest event in the queue
 121   static EventID add_event(const char* format,
 122                            intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) {
 123     // assign a unique id
 124     EventID id = get_next_event_id();
 125 
 126     // event will be copied to buffer[index]
 127     int index = (int)(id % size);
 128 
 129     // first, invalidate id, buffer[index] can't have event with id = index + 2
 130     buffer[index]._id = index + 2;
 131 
 132     // make sure everyone has seen that buffer[index] is invalid
 133     OrderAccess::fence();
 134 
 135     // ... before updating its value
 136     buffer[index].fill(indent, format, arg_1, arg_2, arg_3);
 137 
 138     // finally, set up real event id, now buffer[index] contains valid event
 139     OrderAccess::release_store(&(buffer[index]._id), id);
 140 
 141     return id;
 142   }
 143 
 144   static void print_last(outputStream *st, int number) {
 145     st->print_cr("[Last %d events in the event buffer]", number);
 146     st->print_cr("-<thd>-<elapsed sec>-<description>---------------------");
 147 
 148     int count = 0;
 149     EventID id = _current_event_id;
 150     while (count < number) {
 151       Event event;
 152       if (get_event(id, &event)) {
 153          event.print_on(st);
 154       }
 155       id--;
 156       count++;
 157     }
 158   }
 159 
 160   static void print_all(outputStream* st) {
 161     print_last(st, size);
 162   }
 163 
 164   static void init() {
 165     // Allocate the event buffer
 166     size   = EventLogLength;
 167     buffer = NEW_C_HEAP_ARRAY(Event, size);
 168 
 169     _current_event_id = 0;
 170 
 171     // Clear the event buffer
 172     for (int index = 0; index < size; index++) {
 173       buffer[index]._id = index + 1;       // index + 1 is invalid id
 174       buffer[index].clear();
 175     }
 176   }
 177 };
 178 
 179 Event*           EventBuffer::buffer;
 180 int              EventBuffer::size;
 181 volatile EventID EventBuffer::_current_event_id;
 182 int              EventBuffer::indent;
 183 
 184 ////////////////////////////////////////////////////////////////////////////
 185 // Events
 186 
 187 // Events::log() is safe for signal handlers
 188 void Events::log(const char* format, ...) {
 189   if (LogEvents) {
 190     va_list ap;
 191     va_start(ap, format);
 192     intptr_t arg_1 = va_arg(ap, intptr_t);
 193     intptr_t arg_2 = va_arg(ap, intptr_t);
 194     intptr_t arg_3 = va_arg(ap, intptr_t);
 195     va_end(ap);
 196 
 197     EventBuffer::add_event(format, arg_1, arg_2, arg_3);
 198   }
 199 }
 200 
 201 void Events::print_all(outputStream *st) {
 202   EventBuffer::print_all(st);
 203 }
 204 
 205 void Events::print_last(outputStream *st, int number) {
 206   EventBuffer::print_last(st, number);
 207 }
 208 
 209 ///////////////////////////////////////////////////////////////////////////
 210 // EventMark
 211 
 212 EventMark::EventMark(const char* format, ...) {
 213   if (LogEvents) {
 214     va_list ap;
 215     va_start(ap, format);
 216     intptr_t arg_1 = va_arg(ap, intptr_t);
 217     intptr_t arg_2 = va_arg(ap, intptr_t);
 218     intptr_t arg_3 = va_arg(ap, intptr_t);
 219     va_end(ap);
 220 
 221     EventBuffer::add_event(format, arg_1, arg_2, arg_3);
 222     EventBuffer::inc_indent();
 223   }
 224 }
 225 
 226 EventMark::~EventMark() {
 227   if (LogEvents) {
 228     EventBuffer::dec_indent();
 229     EventBuffer::add_event("done", 0, 0, 0);
 230   }
 231 }
 232 
 233 ///////////////////////////////////////////////////////////////////////////
 234 
 235 void eventlog_init() {
 236   EventBuffer::init();
 237 }
 238 
 239 int print_all_events(outputStream *st) {
 240   EventBuffer::print_all(st);
 241   return 1;
 242 }
 243 
 244 #else
 245 
 246 void eventlog_init() {}
 247 int print_all_events(outputStream *st) { return 0; }
 248 
 249 #endif // PRODUCT