src/share/vm/services/memTrackWorker.cpp

Tue, 27 Nov 2012 14:20:21 +0100

author
stefank
date
Tue, 27 Nov 2012 14:20:21 +0100
changeset 4299
f34d701e952e
parent 4053
33143ee07800
child 4400
ecd24264898b
permissions
-rw-r--r--

8003935: Simplify the needed includes for using Thread::current()
Reviewed-by: dholmes, rbackman, coleenp

     1 /*
     2  * Copyright (c) 2012, 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 "runtime/threadCritical.hpp"
    27 #include "services/memTracker.hpp"
    28 #include "services/memTrackWorker.hpp"
    29 #include "utilities/decoder.hpp"
    30 #include "utilities/vmError.hpp"
    32 MemTrackWorker::MemTrackWorker() {
    33   // create thread uses cgc thread type for now. We should revisit
    34   // the option, or create new thread type.
    35   _has_error = !os::create_thread(this, os::cgc_thread);
    36   set_name("MemTrackWorker", 0);
    38   // initial generation circuit buffer
    39   if (!has_error()) {
    40     _head = _tail = 0;
    41     for(int index = 0; index < MAX_GENERATIONS; index ++) {
    42       _gen[index] = NULL;
    43     }
    44   }
    45   NOT_PRODUCT(_sync_point_count = 0;)
    46   NOT_PRODUCT(_merge_count = 0;)
    47   NOT_PRODUCT(_last_gen_in_use = 0;)
    48 }
    50 MemTrackWorker::~MemTrackWorker() {
    51   for (int index = 0; index < MAX_GENERATIONS; index ++) {
    52     MemRecorder* rc = _gen[index];
    53     if (rc != NULL) {
    54       delete rc;
    55     }
    56   }
    57 }
    59 void* MemTrackWorker::operator new(size_t size) {
    60   assert(false, "use nothrow version");
    61   return NULL;
    62 }
    64 void* MemTrackWorker::operator new(size_t size, const std::nothrow_t& nothrow_constant) {
    65   return allocate(size, false, mtNMT);
    66 }
    68 void MemTrackWorker::start() {
    69   os::start_thread(this);
    70 }
    72 /*
    73  * Native memory tracking worker thread loop:
    74  *   1. merge one generation of memory recorders to staging area
    75  *   2. promote staging data to memory snapshot
    76  *
    77  * This thread can run through safepoint.
    78  */
    80 void MemTrackWorker::run() {
    81   assert(MemTracker::is_on(), "native memory tracking is off");
    82   this->initialize_thread_local_storage();
    83   this->record_stack_base_and_size();
    84   MemSnapshot* snapshot = MemTracker::get_snapshot();
    85   assert(snapshot != NULL, "Worker should not be started");
    86   MemRecorder* rec;
    88   while (!MemTracker::shutdown_in_progress()) {
    89     NOT_PRODUCT(_last_gen_in_use = generations_in_use();)
    90     {
    91       // take a recorder from earliest generation in buffer
    92       ThreadCritical tc;
    93       rec = _gen[_head];
    94       if (rec != NULL) {
    95         _gen[_head] = rec->next();
    96       }
    97       assert(count_recorder(_gen[_head]) <= MemRecorder::_instance_count,
    98         "infinite loop after dequeue");
    99     }
   100     if (rec != NULL) {
   101       // merge the recorder into staging area
   102       if (!snapshot->merge(rec)) {
   103         MemTracker::shutdown(MemTracker::NMT_out_of_memory);
   104       } else {
   105         NOT_PRODUCT(_merge_count ++;)
   106       }
   107       MemTracker::release_thread_recorder(rec);
   108     } else {
   109       // no more recorder to merge, promote staging area
   110       // to snapshot
   111       if (_head != _tail) {
   112         {
   113           ThreadCritical tc;
   114           if (_gen[_head] != NULL || _head == _tail) {
   115             continue;
   116           }
   117           // done with this generation, increment _head pointer
   118           _head = (_head + 1) % MAX_GENERATIONS;
   119         }
   120         // promote this generation data to snapshot
   121         if (!snapshot->promote()) {
   122           // failed to promote, means out of memory
   123           MemTracker::shutdown(MemTracker::NMT_out_of_memory);
   124         }
   125       } else {
   126         snapshot->wait(1000);
   127         ThreadCritical tc;
   128         // check if more data arrived
   129         if (_gen[_head] == NULL) {
   130           _gen[_head] = MemTracker::get_pending_recorders();
   131         }
   132       }
   133     }
   134   }
   135   assert(MemTracker::shutdown_in_progress(), "just check");
   137   // transits to final shutdown
   138   MemTracker::final_shutdown();
   139 }
   141 // at synchronization point, where 'safepoint visible' Java threads are blocked
   142 // at a safepoint, and the rest of threads are blocked on ThreadCritical lock.
   143 // The caller MemTracker::sync() already takes ThreadCritical before calling this
   144 // method.
   145 //
   146 // Following tasks are performed:
   147 //   1. add all recorders in pending queue to current generation
   148 //   2. increase generation
   150 void MemTrackWorker::at_sync_point(MemRecorder* rec) {
   151   NOT_PRODUCT(_sync_point_count ++;)
   152   assert(count_recorder(rec) <= MemRecorder::_instance_count,
   153     "pending queue has infinite loop");
   155   bool out_of_generation_buffer = false;
   156   // check shutdown state inside ThreadCritical
   157   if (MemTracker::shutdown_in_progress()) return;
   158   // append the recorders to the end of the generation
   159   if( rec != NULL) {
   160     MemRecorder* cur_head = _gen[_tail];
   161     if (cur_head == NULL) {
   162       _gen[_tail] = rec;
   163     } else {
   164       while (cur_head->next() != NULL) {
   165         cur_head = cur_head->next();
   166       }
   167       cur_head->set_next(rec);
   168     }
   169   }
   170   assert(count_recorder(rec) <= MemRecorder::_instance_count,
   171     "after add to current generation has infinite loop");
   172   // we have collected all recorders for this generation. If there is data,
   173   // we need to increment _tail to start a new generation.
   174   if (_gen[_tail] != NULL || _head == _tail) {
   175     _tail = (_tail + 1) % MAX_GENERATIONS;
   176     out_of_generation_buffer = (_tail == _head);
   177   }
   179   if (out_of_generation_buffer) {
   180     MemTracker::shutdown(MemTracker::NMT_out_of_generation);
   181   }
   182 }
   184 #ifndef PRODUCT
   185 int MemTrackWorker::count_recorder(const MemRecorder* head) {
   186   int count = 0;
   187   while(head != NULL) {
   188     count ++;
   189     head = head->next();
   190   }
   191   return count;
   192 }
   194 int MemTrackWorker::count_pending_recorders() const {
   195   int count = 0;
   196   for (int index = 0; index < MAX_GENERATIONS; index ++) {
   197     MemRecorder* head = _gen[index];
   198     if (head != NULL) {
   199       count += count_recorder(head);
   200     }
   201   }
   202   return count;
   203 }
   204 #endif

mercurial