src/share/vm/gc_implementation/g1/vm_operations_g1.cpp

Print this page
rev 2755 : 7099824: G1: we should take the pending list lock before doing the remark pause
Summary: Acquire the pending list lock in the prologue method of G1's
concurrent VM_Operation and release the lock in the epilogue() method.
The locking/unlocking order of the pending list lock and the Heap_lock
should match that in the prologue and epilogue methods of VM_GC_Operation.
Reviewed-by:


   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 "gc_implementation/g1/g1CollectedHeap.inline.hpp"
  27 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
  28 #include "gc_implementation/g1/vm_operations_g1.hpp"
  29 #include "gc_implementation/shared/isGCActiveMark.hpp"
  30 #include "gc_implementation/g1/vm_operations_g1.hpp"
  31 #include "runtime/interfaceSupport.hpp"
  32 
  33 VM_G1CollectForAllocation::VM_G1CollectForAllocation(
  34                                                   unsigned int gc_count_before,
  35                                                   size_t word_size)
  36   : VM_G1OperationWithAllocRequest(gc_count_before, word_size) {
  37   guarantee(word_size > 0, "an allocation should always be requested");
  38 }
  39 
  40 void VM_G1CollectForAllocation::doit() {
  41   G1CollectedHeap* g1h = G1CollectedHeap::heap();
  42   _result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
  43   assert(_result == NULL || _pause_succeeded,
  44          "if we get back a result, the pause should have succeeded");
  45 }


 148     // If the condition has already been reached, there's no point in
 149     // actually taking the lock and doing the wait.
 150     if (g1h->full_collections_completed() <=
 151                                           _full_collections_completed_before) {
 152       // The following is largely copied from CMS
 153 
 154       Thread* thr = Thread::current();
 155       assert(thr->is_Java_thread(), "invariant");
 156       JavaThread* jt = (JavaThread*)thr;
 157       ThreadToNativeFromVM native(jt);
 158 
 159       MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
 160       while (g1h->full_collections_completed() <=
 161                                           _full_collections_completed_before) {
 162         FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
 163       }
 164     }
 165   }
 166 }
 167 














 168 void VM_CGC_Operation::doit() {
 169   gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
 170   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
 171   TraceTime t(_printGCMessage, PrintGC, true, gclog_or_tty);
 172   SharedHeap* sh = SharedHeap::heap();
 173   // This could go away if CollectedHeap gave access to _gc_is_active...
 174   if (sh != NULL) {
 175     IsGCActiveMark x;
 176     _cl->do_void();
 177   } else {
 178     _cl->do_void();
 179   }
 180 }
 181 
 182 bool VM_CGC_Operation::doit_prologue() {




 183   Heap_lock->lock();
 184   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true;
 185   return true;
 186 }
 187 
 188 void VM_CGC_Operation::doit_epilogue() {


 189   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false;
 190   Heap_lock->unlock();

 191 }


   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 "gc_implementation/g1/concurrentMarkThread.inline.hpp"
  27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
  28 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
  29 #include "gc_implementation/g1/vm_operations_g1.hpp"
  30 #include "gc_implementation/shared/isGCActiveMark.hpp"
  31 #include "gc_implementation/g1/vm_operations_g1.hpp"
  32 #include "runtime/interfaceSupport.hpp"
  33 
  34 VM_G1CollectForAllocation::VM_G1CollectForAllocation(
  35                                                   unsigned int gc_count_before,
  36                                                   size_t word_size)
  37   : VM_G1OperationWithAllocRequest(gc_count_before, word_size) {
  38   guarantee(word_size > 0, "an allocation should always be requested");
  39 }
  40 
  41 void VM_G1CollectForAllocation::doit() {
  42   G1CollectedHeap* g1h = G1CollectedHeap::heap();
  43   _result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
  44   assert(_result == NULL || _pause_succeeded,
  45          "if we get back a result, the pause should have succeeded");
  46 }


 149     // If the condition has already been reached, there's no point in
 150     // actually taking the lock and doing the wait.
 151     if (g1h->full_collections_completed() <=
 152                                           _full_collections_completed_before) {
 153       // The following is largely copied from CMS
 154 
 155       Thread* thr = Thread::current();
 156       assert(thr->is_Java_thread(), "invariant");
 157       JavaThread* jt = (JavaThread*)thr;
 158       ThreadToNativeFromVM native(jt);
 159 
 160       MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
 161       while (g1h->full_collections_completed() <=
 162                                           _full_collections_completed_before) {
 163         FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
 164       }
 165     }
 166   }
 167 }
 168 
 169 void VM_CGC_Operation::acquire_pending_list_lock() {
 170   // The caller may block while communicating
 171   // with the SLT thread in order to acquire/release the PLL.
 172   ConcurrentMarkThread::slt()->
 173     manipulatePLL(SurrogateLockerThread::acquirePLL);
 174 }
 175 
 176 void VM_CGC_Operation::release_and_notify_pending_list_lock() {
 177   // The caller may block while communicating
 178   // with the SLT thread in order to acquire/release the PLL.
 179   ConcurrentMarkThread::slt()->
 180     manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
 181 }
 182 
 183 void VM_CGC_Operation::doit() {
 184   gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
 185   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
 186   TraceTime t(_printGCMessage, PrintGC, true, gclog_or_tty);
 187   SharedHeap* sh = SharedHeap::heap();
 188   // This could go away if CollectedHeap gave access to _gc_is_active...
 189   if (sh != NULL) {
 190     IsGCActiveMark x;
 191     _cl->do_void();
 192   } else {
 193     _cl->do_void();
 194   }
 195 }
 196 
 197 bool VM_CGC_Operation::doit_prologue() {
 198   // Note the relative order of the locks must match that in
 199   // VM_GC_Operation::doit_prologue() or deadlocks can occur
 200   acquire_pending_list_lock();
 201 
 202   Heap_lock->lock();
 203   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true;
 204   return true;
 205 }
 206 
 207 void VM_CGC_Operation::doit_epilogue() {
 208   // Note the relative order of the unlocks must match that in
 209   // VM_GC_Operation::doit_epilogue()
 210   SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false;
 211   Heap_lock->unlock();
 212   release_and_notify_pending_list_lock();
 213 }