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  */
  24 
  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
  44 
  45 
  46 #ifndef PRODUCT
  47 
  48 ////////////////////////////////////////////////////////////////////////////
  49 // Event
  50 
  51 typedef u4 EventID;
  52 
  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;
  62 
  63   // only EventBuffer::add_event() can assign event id
  64   friend class EventBuffer;
  65   EventID     _id;
  66 
  67  public:
  68 
  69   void clear() { _format = NULL; }
  70 
  71   EventID id() const { return _id; }
  72 
  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;
  78 
  79     _indent = indent;
  80 
  81     _thread_id = os::current_thread_id();
  82     _time_tick = os::elapsed_counter();
  83   }
  84 
  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 };
  96 
  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.
 107 
 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;
 114 
 115   static EventID get_next_event_id() {
 116     return (EventID)Atomic::add(1, (jint*)&_current_event_id);
 117   }
 118 
 119  public:
 120   static void inc_indent() { Atomic::inc(&indent); }
 121   static void dec_indent() { Atomic::dec(&indent); }
 122 
 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   }
 135 
 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();
 142 
 143     // event will be copied to buffer[index]
 144     int index = (int)(id % size);
 145 
 146     // first, invalidate id, buffer[index] can't have event with id = index + 2
 147     buffer[index]._id = index + 2;
 148 
 149     // make sure everyone has seen that buffer[index] is invalid
 150     OrderAccess::fence();
 151 
 152     // ... before updating its value
 153     buffer[index].fill(indent, format, arg_1, arg_2, arg_3);
 154 
 155     // finally, set up real event id, now buffer[index] contains valid event
 156     OrderAccess::release_store(&(buffer[index]._id), id);
 157 
 158     return id;
 159   }
 160 
 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>---------------------");
 164 
 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   }
 176 
 177   static void print_all(outputStream* st) {
 178     print_last(st, size);
 179   }
 180 
 181   static void init() {
 182     // Allocate the event buffer
 183     size   = EventLogLength;
 184     buffer = NEW_C_HEAP_ARRAY(Event, size);
 185 
 186     _current_event_id = 0;
 187 
 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 };
 195 
 196 Event*           EventBuffer::buffer;
 197 int              EventBuffer::size;
 198 volatile EventID EventBuffer::_current_event_id;
 199 int              EventBuffer::indent;
 200 
 201 ////////////////////////////////////////////////////////////////////////////
 202 // Events
 203 
 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);
 213 
 214     EventBuffer::add_event(format, arg_1, arg_2, arg_3);
 215   }
 216 }
 217 
 218 void Events::print_all(outputStream *st) {
 219   EventBuffer::print_all(st);
 220 }
 221 
 222 void Events::print_last(outputStream *st, int number) {
 223   EventBuffer::print_last(st, number);
 224 }
 225 
 226 ///////////////////////////////////////////////////////////////////////////
 227 // EventMark
 228 
 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);
 237 
 238     EventBuffer::add_event(format, arg_1, arg_2, arg_3);
 239     EventBuffer::inc_indent();
 240   }
 241 }
 242 
 243 EventMark::~EventMark() {
 244   if (LogEvents) {
 245     EventBuffer::dec_indent();
 246     EventBuffer::add_event("done", 0, 0, 0);
 247   }
 248 }
 249 
 250 ///////////////////////////////////////////////////////////////////////////
 251 
 252 void eventlog_init() {
 253   EventBuffer::init();
 254 }
 255 
 256 int print_all_events(outputStream *st) {
 257   EventBuffer::print_all(st);
 258   return 1;
 259 }
 260 
 261 #else
 262 
 263 void eventlog_init() {}
 264 int print_all_events(outputStream *st) { return 0; }
 265 
 266 #endif // PRODUCT