1 /*
   2  * Copyright (c) 2001, 2005, 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/_perfData.cpp.incl"
  27 
  28 PerfDataList*   PerfDataManager::_all = NULL;
  29 PerfDataList*   PerfDataManager::_sampled = NULL;
  30 PerfDataList*   PerfDataManager::_constants = NULL;
  31 
  32 /*
  33  * The jvmstat global and subsysem jvmstat counter name spaces. The top
  34  * level name spaces imply the interface stability level of the counter,
  35  * which generally follows the Java package, class, and property naming
  36  * conventions. The CounterNS enumeration values should be used to index
  37  * into this array.
  38  */
  39 const char* PerfDataManager::_name_spaces[] = {
  40   // top level name spaces
  41   "java",                   // stable and supported name space
  42   "com.sun",                // unstable but supported name space
  43   "sun",                    // unstable and unsupported name space
  44   // subsystem name spaces
  45   "java.gc",                // Garbage Collection name spaces
  46   "com.sun.gc",
  47   "sun.gc",
  48   "java.ci",                // Compiler name spaces
  49   "com.sun.ci",
  50   "sun.ci",
  51   "java.cls",               // Class Loader name spaces
  52   "com.sun.cls",
  53   "sun.cls",
  54   "java.rt",                // Runtime name spaces
  55   "com.sun.rt",
  56   "sun.rt",
  57   "java.os",                // Operating System name spaces
  58   "com.sun.os",
  59   "sun.os",
  60   "java.threads",           // Threads System name spaces
  61   "com.sun.threads",
  62   "sun.threads",
  63   "java.property",          // Java Property name spaces
  64   "com.sun.property",
  65   "sun.property",
  66   "",
  67 };
  68 
  69 PerfData::PerfData(CounterNS ns, const char* name, Units u, Variability v)
  70                   : _name(NULL), _u(u), _v(v), _valuep(NULL),
  71                     _on_c_heap(false) {
  72 
  73   const char* prefix = PerfDataManager::ns_to_string(ns);
  74 
  75   _name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2);
  76   assert(_name != NULL && strlen(name) != 0, "invalid name");
  77 
  78   if (ns == NULL_NS) {
  79      // No prefix is added to counters with the NULL_NS namespace.
  80      strcpy(_name, name);
  81      // set the F_Supported flag based on the counter name prefix.
  82      if (PerfDataManager::is_stable_supported(_name) ||
  83          PerfDataManager::is_unstable_supported(_name)) {
  84        _flags = F_Supported;
  85      }
  86      else {
  87        _flags = F_None;
  88      }
  89   }
  90   else {
  91     sprintf(_name, "%s.%s", prefix, name);
  92     // set the F_Supported flag based on the given namespace.
  93     if (PerfDataManager::is_stable_supported(ns) ||
  94         PerfDataManager::is_unstable_supported(ns)) {
  95       _flags = F_Supported;
  96     }
  97     else {
  98       _flags = F_None;
  99     }
 100   }
 101 }
 102 
 103 PerfData::~PerfData() {
 104   if (_name != NULL) {
 105     FREE_C_HEAP_ARRAY(char, _name);
 106   }
 107   if (is_on_c_heap()) {
 108     FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep);
 109   }
 110 }
 111 
 112 void PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) {
 113 
 114   size_t dlen = vlen==0 ? 1 : vlen;
 115 
 116   size_t namelen = strlen(name()) + 1;  // include null terminator
 117   size_t size = sizeof(PerfDataEntry) + namelen;
 118   size_t pad_length = ((size % dsize) == 0) ? 0 : dsize - (size % dsize);
 119   size += pad_length;
 120   size_t data_start = size;
 121   size += (dsize * dlen);
 122 
 123   // align size to assure allocation in units of 8 bytes
 124   int align = sizeof(jlong) - 1;
 125   size = ((size + align) & ~align);
 126   char* psmp = PerfMemory::alloc(size);
 127 
 128   if (psmp == NULL) {
 129     // out of PerfMemory memory resources. allocate on the C heap
 130     // to avoid vm termination.
 131     psmp = NEW_C_HEAP_ARRAY(char, size);
 132     _on_c_heap = true;
 133   }
 134 
 135   // compute the addresses for the name and data
 136   char* cname = psmp + sizeof(PerfDataEntry);
 137 
 138   // data is in the last dsize*dlen bytes of the entry
 139   void* valuep = (void*) (psmp + data_start);
 140 
 141   assert(is_on_c_heap() || PerfMemory::contains(cname), "just checking");
 142   assert(is_on_c_heap() || PerfMemory::contains((char*)valuep), "just checking");
 143 
 144   // copy the name, including null terminator, into PerfData memory
 145   strcpy(cname, name());
 146 
 147 
 148   // set the header values in PerfData memory
 149   PerfDataEntry* pdep = (PerfDataEntry*)psmp;
 150   pdep->entry_length = (jint)size;
 151   pdep->name_offset = (jint) ((uintptr_t) cname - (uintptr_t) psmp);
 152   pdep->vector_length = (jint)vlen;
 153   pdep->data_type = (jbyte) type2char(dtype);
 154   pdep->data_units = units();
 155   pdep->data_variability = variability();
 156   pdep->flags = (jbyte)flags();
 157   pdep->data_offset = (jint) data_start;
 158 
 159   if (PerfTraceDataCreation) {
 160     tty->print("name = %s, dtype = %d, variability = %d,"
 161                " units = %d, dsize = %d, vlen = %d,"
 162                " pad_length = %d, size = %d, on_c_heap = %s,"
 163                " address = " INTPTR_FORMAT ","
 164                " data address = " INTPTR_FORMAT "\n",
 165                cname, dtype, variability(),
 166                units(), dsize, vlen,
 167                pad_length, size, is_on_c_heap() ? "TRUE":"FALSE",
 168                psmp, valuep);
 169   }
 170 
 171   // record the start of the entry and the location of the data field.
 172   _pdep = pdep;
 173   _valuep = valuep;
 174 
 175   // mark the PerfData memory region as having been updated.
 176   PerfMemory::mark_updated();
 177 }
 178 
 179 PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v)
 180                  : PerfData(ns, namep, u, v) {
 181 
 182   create_entry(T_LONG, sizeof(jlong));
 183 }
 184 
 185 int PerfLong::format(char* buffer, int length) {
 186   return jio_snprintf(buffer, length,"%lld", *(jlong*)_valuep);
 187 }
 188 
 189 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
 190                                  Variability v, jlong* sampled)
 191                                 : PerfLong(ns, namep, u, v),
 192                                   _sampled(sampled), _sample_helper(NULL) {
 193 
 194   sample();
 195 }
 196 
 197 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
 198                                  Variability v, PerfLongSampleHelper* helper)
 199                                 : PerfLong(ns, namep, u, v),
 200                                   _sampled(NULL), _sample_helper(helper) {
 201 
 202   sample();
 203 }
 204 
 205 void PerfLongVariant::sample() {
 206 
 207   assert(_sample_helper != NULL || _sampled != NULL, "unexpected state");
 208 
 209   if (_sample_helper != NULL) {
 210     *(jlong*)_valuep = _sample_helper->take_sample();
 211   }
 212   else if (_sampled != NULL) {
 213     *(jlong*)_valuep = *_sampled;
 214   }
 215 }
 216 
 217 PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u,
 218                              Variability v, jint length)
 219                             : PerfData(ns, namep, u, v), _length(length) {
 220 
 221   create_entry(T_BYTE, sizeof(jbyte), (size_t)_length);
 222 }
 223 
 224 void PerfString::set_string(const char* s2) {
 225 
 226   // copy n bytes of the string, assuring the null string is
 227   // copied if s2 == NULL.
 228   strncpy((char *)_valuep, s2 == NULL ? "" : s2, _length);
 229 
 230   // assure the string is null terminated when strlen(s2) >= _length
 231   ((char*)_valuep)[_length-1] = '\0';
 232 }
 233 
 234 int PerfString::format(char* buffer, int length) {
 235   return jio_snprintf(buffer, length, "%s", (char*)_valuep);
 236 }
 237 
 238 PerfStringConstant::PerfStringConstant(CounterNS ns, const char* namep,
 239                                        const char* initial_value)
 240                      : PerfString(ns, namep, V_Constant,
 241                                   initial_value == NULL ? 1 :
 242                                   MIN2((jint)(strlen((char*)initial_value)+1),
 243                                        (jint)(PerfMaxStringConstLength+1)),
 244                                   initial_value) {
 245 
 246   if (PrintMiscellaneous && Verbose) {
 247     if (is_valid() && initial_value != NULL &&
 248         ((jint)strlen(initial_value) > (jint)PerfMaxStringConstLength)) {
 249 
 250       warning("Truncating PerfStringConstant: name = %s,"
 251               " length = " INT32_FORMAT ","
 252               " PerfMaxStringConstLength = " INT32_FORMAT "\n",
 253               namep,
 254               (jint)strlen(initial_value),
 255               (jint)PerfMaxStringConstLength);
 256     }
 257   }
 258 }
 259 
 260 
 261 
 262 
 263 
 264 
 265 void PerfDataManager::destroy() {
 266 
 267   if (_all == NULL)
 268     // destroy already called, or initialization never happened
 269     return;
 270 
 271   for (int index = 0; index < _all->length(); index++) {
 272     PerfData* p = _all->at(index);
 273     delete p;
 274   }
 275 
 276   delete(_all);
 277   delete(_sampled);
 278   delete(_constants);
 279 
 280   _all = NULL;
 281   _sampled = NULL;
 282   _constants = NULL;
 283 }
 284 
 285 void PerfDataManager::add_item(PerfData* p, bool sampled) {
 286 
 287   MutexLocker ml(PerfDataManager_lock);
 288 
 289   if (_all == NULL) {
 290     _all = new PerfDataList(100);
 291   }
 292 
 293   assert(!_all->contains(p->name()), "duplicate name added");
 294 
 295   // add to the list of all perf data items
 296   _all->append(p);
 297 
 298   if (p->variability() == PerfData::V_Constant) {
 299     if (_constants == NULL) {
 300       _constants = new PerfDataList(25);
 301     }
 302     _constants->append(p);
 303     return;
 304   }
 305 
 306   if (sampled) {
 307     if (_sampled == NULL) {
 308       _sampled = new PerfDataList(25);
 309     }
 310     _sampled->append(p);
 311   }
 312 }
 313 
 314 PerfDataList* PerfDataManager::all() {
 315 
 316   MutexLocker ml(PerfDataManager_lock);
 317 
 318   if (_all == NULL)
 319     return NULL;
 320 
 321   PerfDataList* clone = _all->clone();
 322   return clone;
 323 }
 324 
 325 PerfDataList* PerfDataManager::sampled() {
 326 
 327   MutexLocker ml(PerfDataManager_lock);
 328 
 329   if (_sampled == NULL)
 330     return NULL;
 331 
 332   PerfDataList* clone = _sampled->clone();
 333   return clone;
 334 }
 335 
 336 PerfDataList* PerfDataManager::constants() {
 337 
 338   MutexLocker ml(PerfDataManager_lock);
 339 
 340   if (_constants == NULL)
 341     return NULL;
 342 
 343   PerfDataList* clone = _constants->clone();
 344   return clone;
 345 }
 346 
 347 char* PerfDataManager::counter_name(const char* ns, const char* name) {
 348    assert(ns != NULL, "ns string required");
 349    assert(name != NULL, "name string required");
 350 
 351    size_t len = strlen(ns) + strlen(name) + 2;
 352    char* result = NEW_RESOURCE_ARRAY(char, len);
 353    sprintf(result, "%s.%s", ns, name);
 354    return result;
 355 }
 356 
 357 char* PerfDataManager::name_space(const char* ns, const char* sub,
 358                                   int instance) {
 359    char intbuf[40];
 360    jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
 361    return name_space(ns, name_space(sub, intbuf));
 362 }
 363 
 364 char *PerfDataManager::name_space(const char* ns, int instance) {
 365    char intbuf[40];
 366    jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
 367    return name_space(ns, intbuf);
 368 }
 369 
 370 PerfStringConstant* PerfDataManager::create_string_constant(CounterNS ns,
 371                                                             const char* name,
 372                                                             const char* s,
 373                                                             TRAPS) {
 374 
 375   PerfStringConstant* p = new PerfStringConstant(ns, name, s);
 376 
 377   if (!p->is_valid()) {
 378     // allocation of native resources failed.
 379     delete p;
 380     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 381   }
 382 
 383   add_item(p, false);
 384 
 385   return p;
 386 }
 387 
 388 PerfLongConstant* PerfDataManager::create_long_constant(CounterNS ns,
 389                                                         const char* name,
 390                                                         PerfData::Units u,
 391                                                         jlong val, TRAPS) {
 392 
 393   PerfLongConstant* p = new PerfLongConstant(ns, name, u, val);
 394 
 395   if (!p->is_valid()) {
 396     // allocation of native resources failed.
 397     delete p;
 398     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 399   }
 400 
 401   add_item(p, false);
 402 
 403   return p;
 404 }
 405 
 406 PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns,
 407                                                             const char* name,
 408                                                             jint max_length,
 409                                                             const char* s,
 410                                                             TRAPS) {
 411 
 412   if (max_length == 0 && s != NULL) max_length = (jint)strlen(s);
 413 
 414   assert(max_length != 0, "PerfStringVariable with length 0");
 415 
 416   PerfStringVariable* p = new PerfStringVariable(ns, name, max_length, s);
 417 
 418   if (!p->is_valid()) {
 419     // allocation of native resources failed.
 420     delete p;
 421     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 422   }
 423 
 424   add_item(p, false);
 425 
 426   return p;
 427 }
 428 
 429 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
 430                                                         const char* name,
 431                                                         PerfData::Units u,
 432                                                         jlong ival, TRAPS) {
 433 
 434   PerfLongVariable* p = new PerfLongVariable(ns, name, u, ival);
 435 
 436   if (!p->is_valid()) {
 437     // allocation of native resources failed.
 438     delete p;
 439     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 440   }
 441 
 442   add_item(p, false);
 443 
 444   return p;
 445 }
 446 
 447 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
 448                                                         const char* name,
 449                                                         PerfData::Units u,
 450                                                         jlong* sp, TRAPS) {
 451 
 452   // Sampled counters not supported if UsePerfData is false
 453   if (!UsePerfData) return NULL;
 454 
 455   PerfLongVariable* p = new PerfLongVariable(ns, name, u, sp);
 456 
 457   if (!p->is_valid()) {
 458     // allocation of native resources failed.
 459     delete p;
 460     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 461   }
 462 
 463   add_item(p, true);
 464 
 465   return p;
 466 }
 467 
 468 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
 469                                                         const char* name,
 470                                                         PerfData::Units u,
 471                                                         PerfSampleHelper* sh,
 472                                                         TRAPS) {
 473 
 474   // Sampled counters not supported if UsePerfData is false
 475   if (!UsePerfData) return NULL;
 476 
 477   PerfLongVariable* p = new PerfLongVariable(ns, name, u, sh);
 478 
 479   if (!p->is_valid()) {
 480     // allocation of native resources failed.
 481     delete p;
 482     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 483   }
 484 
 485   add_item(p, true);
 486 
 487   return p;
 488 }
 489 
 490 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
 491                                                       const char* name,
 492                                                       PerfData::Units u,
 493                                                       jlong ival, TRAPS) {
 494 
 495   PerfLongCounter* p = new PerfLongCounter(ns, name, u, ival);
 496 
 497   if (!p->is_valid()) {
 498     // allocation of native resources failed.
 499     delete p;
 500     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 501   }
 502 
 503   add_item(p, false);
 504 
 505   return p;
 506 }
 507 
 508 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
 509                                                       const char* name,
 510                                                       PerfData::Units u,
 511                                                       jlong* sp, TRAPS) {
 512 
 513   // Sampled counters not supported if UsePerfData is false
 514   if (!UsePerfData) return NULL;
 515 
 516   PerfLongCounter* p = new PerfLongCounter(ns, name, u, sp);
 517 
 518   if (!p->is_valid()) {
 519     // allocation of native resources failed.
 520     delete p;
 521     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 522   }
 523 
 524   add_item(p, true);
 525 
 526   return p;
 527 }
 528 
 529 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
 530                                                       const char* name,
 531                                                       PerfData::Units u,
 532                                                       PerfSampleHelper* sh,
 533                                                       TRAPS) {
 534 
 535   // Sampled counters not supported if UsePerfData is false
 536   if (!UsePerfData) return NULL;
 537 
 538   PerfLongCounter* p = new PerfLongCounter(ns, name, u, sh);
 539 
 540   if (!p->is_valid()) {
 541     // allocation of native resources failed.
 542     delete p;
 543     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
 544   }
 545 
 546   add_item(p, true);
 547 
 548   return p;
 549 }
 550 
 551 PerfDataList::PerfDataList(int length) {
 552 
 553   _set = new(ResourceObj::C_HEAP) PerfDataArray(length, true);
 554 }
 555 
 556 PerfDataList::PerfDataList(PerfDataList* p) {
 557 
 558   _set = new(ResourceObj::C_HEAP) PerfDataArray(p->length(), true);
 559 
 560   _set->appendAll(p->get_impl());
 561 }
 562 
 563 PerfDataList::~PerfDataList() {
 564 
 565   delete _set;
 566 
 567 }
 568 
 569 bool PerfDataList::by_name(void* name, PerfData* pd) {
 570 
 571   if (pd == NULL)
 572     return false;
 573 
 574   return strcmp((const char*)name, pd->name()) == 0;
 575 }
 576 
 577 PerfData* PerfDataList::find_by_name(const char* name) {
 578 
 579   int i = _set->find((void*)name, PerfDataList::by_name);
 580 
 581   if (i >= 0 && i <= _set->length())
 582     return _set->at(i);
 583   else
 584     return NULL;
 585 }
 586 
 587 PerfDataList* PerfDataList::clone() {
 588 
 589   PerfDataList* copy = new PerfDataList(this);
 590 
 591   assert(copy != NULL, "just checking");
 592 
 593   return copy;
 594 }