src/share/vm/gc_implementation/g1/collectionSetChooser.hpp

Mon, 12 Mar 2012 14:59:00 -0700

author
johnc
date
Mon, 12 Mar 2012 14:59:00 -0700
changeset 3666
64bf7c8270cb
parent 3539
a9647476d1a4
child 3713
720b6a76dd9d
permissions
-rw-r--r--

7147724: G1: hang in SurrogateLockerThread::manipulatePLL
Summary: Attempting to initiate a marking cycle when allocating a humongous object can, if a marking cycle is successfully initiated by another thread, result in the allocating thread spinning until the marking cycle is complete. Eliminate a deadlock between the main ConcurrentMarkThread, the SurrogateLocker thread, the VM thread, and a mutator thread waiting on the SecondaryFreeList_lock (while free regions are going to become available) by not manipulating the pending list lock during the prologue and epilogue of the cleanup pause.
Reviewed-by: brutisso, jcoomes, tonyp

     1 /*
     2  * Copyright (c) 2001, 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 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP
    26 #define SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP
    28 #include "gc_implementation/g1/heapRegion.hpp"
    29 #include "utilities/growableArray.hpp"
    31 class CSetChooserCache VALUE_OBJ_CLASS_SPEC {
    32 private:
    33   enum {
    34     CacheLength = 16
    35   } PrivateConstants;
    37   HeapRegion*  _cache[CacheLength];
    38   int          _occupancy; // number of regions in cache
    39   int          _first;     // (index of) "first" region in the cache
    41   // adding CacheLength to deal with negative values
    42   inline int trim_index(int index) {
    43     return (index + CacheLength) % CacheLength;
    44   }
    46   inline int get_sort_index(int index) {
    47     return -index-2;
    48   }
    49   inline int get_index(int sort_index) {
    50     return -sort_index-2;
    51   }
    53 public:
    54   CSetChooserCache(void);
    56   inline int occupancy(void) { return _occupancy; }
    57   inline bool is_full()      { return _occupancy == CacheLength; }
    58   inline bool is_empty()     { return _occupancy == 0; }
    60   void clear(void);
    61   void insert(HeapRegion *hr);
    62   HeapRegion *remove_first(void);
    63   inline HeapRegion *get_first(void) {
    64     return _cache[_first];
    65   }
    67 #ifndef PRODUCT
    68   bool verify (void);
    69   bool region_in_cache(HeapRegion *hr) {
    70     int sort_index = hr->sort_index();
    71     if (sort_index < -1) {
    72       int index = get_index(sort_index);
    73       guarantee(index < CacheLength, "should be within bounds");
    74       return _cache[index] == hr;
    75     } else
    76       return 0;
    77   }
    78 #endif // PRODUCT
    79 };
    81 class CollectionSetChooser: public CHeapObj {
    83   GrowableArray<HeapRegion*> _markedRegions;
    85   // The index of the next candidate old region to be considered for
    86   // addition to the CSet.
    87   int _curr_index;
    89   // The number of candidate old regions added to the CSet chooser.
    90   int _length;
    92   CSetChooserCache _cache;
    93   jint _first_par_unreserved_idx;
    95   // If a region has more live bytes than this threshold, it will not
    96   // be added to the CSet chooser and will not be a candidate for
    97   // collection.
    98   size_t _regionLiveThresholdBytes;
   100   // The sum of reclaimable bytes over all the regions in the CSet chooser.
   101   size_t _remainingReclaimableBytes;
   103 public:
   105   // Return the current candidate region to be considered for
   106   // collection without removing it from the CSet chooser.
   107   HeapRegion* peek() {
   108     HeapRegion* res = NULL;
   109     if (_curr_index < _length) {
   110       res = _markedRegions.at(_curr_index);
   111       assert(res != NULL,
   112              err_msg("Unexpected NULL hr in _markedRegions at index %d",
   113                      _curr_index));
   114     }
   115     return res;
   116   }
   118   // Remove the given region from the CSet chooser and move to the
   119   // next one. The given region should be the current candidate region
   120   // in the CSet chooser.
   121   void remove_and_move_to_next(HeapRegion* hr) {
   122     assert(hr != NULL, "pre-condition");
   123     assert(_curr_index < _length, "pre-condition");
   124     assert(_markedRegions.at(_curr_index) == hr, "pre-condition");
   125     hr->set_sort_index(-1);
   126     _markedRegions.at_put(_curr_index, NULL);
   127     assert(hr->reclaimable_bytes() <= _remainingReclaimableBytes,
   128            err_msg("remaining reclaimable bytes inconsistent "
   129                    "from region: "SIZE_FORMAT" remaining: "SIZE_FORMAT,
   130                    hr->reclaimable_bytes(), _remainingReclaimableBytes));
   131     _remainingReclaimableBytes -= hr->reclaimable_bytes();
   132     _curr_index += 1;
   133   }
   135   CollectionSetChooser();
   137   void sortMarkedHeapRegions();
   138   void fillCache();
   140   // Determine whether to add the given region to the CSet chooser or
   141   // not. Currently, we skip humongous regions (we never add them to
   142   // the CSet, we only reclaim them during cleanup) and regions whose
   143   // live bytes are over the threshold.
   144   bool shouldAdd(HeapRegion* hr) {
   145     assert(hr->is_marked(), "pre-condition");
   146     assert(!hr->is_young(), "should never consider young regions");
   147     return !hr->isHumongous() &&
   148             hr->live_bytes() < _regionLiveThresholdBytes;
   149   }
   151   // Calculate the minimum number of old regions we'll add to the CSet
   152   // during a mixed GC.
   153   size_t calcMinOldCSetLength();
   155   // Calculate the maximum number of old regions we'll add to the CSet
   156   // during a mixed GC.
   157   size_t calcMaxOldCSetLength();
   159   // Serial version.
   160   void addMarkedHeapRegion(HeapRegion *hr);
   162   // Must be called before calls to getParMarkedHeapRegionChunk.
   163   // "n_regions" is the number of regions, "chunkSize" the chunk size.
   164   void prepareForAddMarkedHeapRegionsPar(size_t n_regions, size_t chunkSize);
   165   // Returns the first index in a contiguous chunk of "n_regions" indexes
   166   // that the calling thread has reserved.  These must be set by the
   167   // calling thread using "setMarkedHeapRegion" (to NULL if necessary).
   168   jint getParMarkedHeapRegionChunk(jint n_regions);
   169   // Set the marked array entry at index to hr.  Careful to claim the index
   170   // first if in parallel.
   171   void setMarkedHeapRegion(jint index, HeapRegion* hr);
   172   // Atomically increment the number of added regions by region_num
   173   // and the amount of reclaimable bytes by reclaimable_bytes.
   174   void updateTotals(jint region_num, size_t reclaimable_bytes);
   176   void clearMarkedHeapRegions();
   178   // Return the number of candidate regions that remain to be collected.
   179   size_t remainingRegions() { return _length - _curr_index; }
   181   // Determine whether the CSet chooser has more candidate regions or not.
   182   bool isEmpty() { return remainingRegions() == 0; }
   184   // Return the reclaimable bytes that remain to be collected on
   185   // all the candidate regions in the CSet chooser.
   186   size_t remainingReclaimableBytes () { return _remainingReclaimableBytes; }
   188   // Returns true if the used portion of "_markedRegions" is properly
   189   // sorted, otherwise asserts false.
   190 #ifndef PRODUCT
   191   bool verify(void);
   192   bool regionProperlyOrdered(HeapRegion* r) {
   193     int si = r->sort_index();
   194     if (si > -1) {
   195       guarantee(_curr_index <= si && si < _length,
   196                 err_msg("curr: %d sort index: %d: length: %d",
   197                         _curr_index, si, _length));
   198       guarantee(_markedRegions.at(si) == r,
   199                 err_msg("sort index: %d at: "PTR_FORMAT" r: "PTR_FORMAT,
   200                         si, _markedRegions.at(si), r));
   201     } else {
   202       guarantee(si == -1, err_msg("sort index: %d", si));
   203     }
   204     return true;
   205   }
   206 #endif
   208 };
   210 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_COLLECTIONSETCHOOSER_HPP

mercurial