src/share/vm/gc_implementation/shared/concurrentGCThread.cpp

Thu, 20 Oct 2011 12:06:20 -0700

author
johnc
date
Thu, 20 Oct 2011 12:06:20 -0700
changeset 3218
db89aa49298f
parent 2964
2a241e764894
child 4037
da91efe96a93
permissions
-rw-r--r--

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: tonyp, ysr

     1 /*
     2  * Copyright (c) 2001, 2011, 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 "classfile/systemDictionary.hpp"
    27 #include "gc_implementation/shared/concurrentGCThread.hpp"
    28 #include "oops/instanceRefKlass.hpp"
    29 #include "oops/oop.inline.hpp"
    30 #include "runtime/init.hpp"
    31 #include "runtime/interfaceSupport.hpp"
    32 #include "runtime/java.hpp"
    33 #include "runtime/javaCalls.hpp"
    35 // CopyrightVersion 1.2
    37 int  ConcurrentGCThread::_CGC_flag            = CGC_nil;
    39 SuspendibleThreadSet ConcurrentGCThread::_sts;
    41 ConcurrentGCThread::ConcurrentGCThread() :
    42   _should_terminate(false), _has_terminated(false) {
    43   _sts.initialize();
    44 };
    46 void ConcurrentGCThread::safepoint_synchronize() {
    47   _sts.suspend_all();
    48 }
    50 void ConcurrentGCThread::safepoint_desynchronize() {
    51   _sts.resume_all();
    52 }
    54 void ConcurrentGCThread::create_and_start() {
    55   if (os::create_thread(this, os::cgc_thread)) {
    56     // XXX: need to set this to low priority
    57     // unless "agressive mode" set; priority
    58     // should be just less than that of VMThread.
    59     os::set_priority(this, NearMaxPriority);
    60     if (!_should_terminate && !DisableStartThread) {
    61       os::start_thread(this);
    62     }
    63   }
    64 }
    66 void ConcurrentGCThread::initialize_in_thread() {
    67   this->record_stack_base_and_size();
    68   this->initialize_thread_local_storage();
    69   this->set_active_handles(JNIHandleBlock::allocate_block());
    70   // From this time Thread::current() should be working.
    71   assert(this == Thread::current(), "just checking");
    72 }
    74 void ConcurrentGCThread::wait_for_universe_init() {
    75   MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
    76   while (!is_init_completed() && !_should_terminate) {
    77     CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200);
    78   }
    79 }
    81 void ConcurrentGCThread::terminate() {
    82   // Signal that it is terminated
    83   {
    84     MutexLockerEx mu(Terminator_lock,
    85                      Mutex::_no_safepoint_check_flag);
    86     _has_terminated = true;
    87     Terminator_lock->notify();
    88   }
    90   // Thread destructor usually does this..
    91   ThreadLocalStorage::set_thread(NULL);
    92 }
    95 void SuspendibleThreadSet::initialize_work() {
    96   MutexLocker x(STS_init_lock);
    97   if (!_initialized) {
    98     _m             = new Monitor(Mutex::leaf,
    99                                  "SuspendibleThreadSetLock", true);
   100     _async         = 0;
   101     _async_stop    = false;
   102     _async_stopped = 0;
   103     _initialized   = true;
   104   }
   105 }
   107 void SuspendibleThreadSet::join() {
   108   initialize();
   109   MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
   110   while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
   111   _async++;
   112   assert(_async > 0, "Huh.");
   113 }
   115 void SuspendibleThreadSet::leave() {
   116   assert(_initialized, "Must be initialized.");
   117   MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
   118   _async--;
   119   assert(_async >= 0, "Huh.");
   120   if (_async_stop) _m->notify_all();
   121 }
   123 void SuspendibleThreadSet::yield(const char* id) {
   124   assert(_initialized, "Must be initialized.");
   125   if (_async_stop) {
   126     MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
   127     if (_async_stop) {
   128       _async_stopped++;
   129       assert(_async_stopped > 0, "Huh.");
   130       if (_async_stopped == _async) {
   131         if (ConcGCYieldTimeout > 0) {
   132           double now = os::elapsedTime();
   133           guarantee((now - _suspend_all_start) * 1000.0 <
   134                     (double)ConcGCYieldTimeout,
   135                     "Long delay; whodunit?");
   136         }
   137       }
   138       _m->notify_all();
   139       while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
   140       _async_stopped--;
   141       assert(_async >= 0, "Huh");
   142       _m->notify_all();
   143     }
   144   }
   145 }
   147 void SuspendibleThreadSet::suspend_all() {
   148   initialize();  // If necessary.
   149   if (ConcGCYieldTimeout > 0) {
   150     _suspend_all_start = os::elapsedTime();
   151   }
   152   MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
   153   assert(!_async_stop, "Only one at a time.");
   154   _async_stop = true;
   155   while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag);
   156 }
   158 void SuspendibleThreadSet::resume_all() {
   159   assert(_initialized, "Must be initialized.");
   160   MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
   161   assert(_async_stopped == _async, "Huh.");
   162   _async_stop = false;
   163   _m->notify_all();
   164 }
   166 static void _sltLoop(JavaThread* thread, TRAPS) {
   167   SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
   168   slt->loop();
   169 }
   171 SurrogateLockerThread::SurrogateLockerThread() :
   172   JavaThread(&_sltLoop),
   173   _monitor(Mutex::nonleaf, "SLTMonitor"),
   174   _buffer(empty)
   175 {}
   177 SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
   178   klassOop k =
   179     SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
   180                                       true, CHECK_NULL);
   181   instanceKlassHandle klass (THREAD, k);
   182   instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
   184   const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)";
   185   Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);
   187   // Initialize thread_oop to put it into the system threadGroup
   188   Handle thread_group (THREAD, Universe::system_thread_group());
   189   JavaValue result(T_VOID);
   190   JavaCalls::call_special(&result, thread_oop,
   191                           klass,
   192                           vmSymbols::object_initializer_name(),
   193                           vmSymbols::threadgroup_string_void_signature(),
   194                           thread_group,
   195                           string,
   196                           CHECK_NULL);
   198   SurrogateLockerThread* res;
   199   {
   200     MutexLocker mu(Threads_lock);
   201     res = new SurrogateLockerThread();
   203     // At this point it may be possible that no osthread was created for the
   204     // JavaThread due to lack of memory. We would have to throw an exception
   205     // in that case. However, since this must work and we do not allow
   206     // exceptions anyway, check and abort if this fails.
   207     if (res == NULL || res->osthread() == NULL) {
   208       vm_exit_during_initialization("java.lang.OutOfMemoryError",
   209                                     "unable to create new native thread");
   210     }
   211     java_lang_Thread::set_thread(thread_oop(), res);
   212     java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
   213     java_lang_Thread::set_daemon(thread_oop());
   215     res->set_threadObj(thread_oop());
   216     Threads::add(res);
   217     Thread::start(res);
   218   }
   219   os::yield(); // This seems to help with initial start-up of SLT
   220   return res;
   221 }
   223 void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
   224   MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
   225   assert(_buffer == empty, "Should be empty");
   226   assert(msg != empty, "empty message");
   227   assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
   229   _buffer = msg;
   230   while (_buffer != empty) {
   231     _monitor.notify();
   232     _monitor.wait(Mutex::_no_safepoint_check_flag);
   233   }
   234 }
   236 // ======= Surrogate Locker Thread =============
   238 void SurrogateLockerThread::loop() {
   239   BasicLock pll_basic_lock;
   240   SLT_msg_type msg;
   241   debug_only(unsigned int owned = 0;)
   243   while (/* !isTerminated() */ 1) {
   244     {
   245       MutexLocker x(&_monitor);
   246       // Since we are a JavaThread, we can't be here at a safepoint.
   247       assert(!SafepointSynchronize::is_at_safepoint(),
   248              "SLT is a JavaThread");
   249       // wait for msg buffer to become non-empty
   250       while (_buffer == empty) {
   251         _monitor.notify();
   252         _monitor.wait();
   253       }
   254       msg = _buffer;
   255     }
   256     switch(msg) {
   257       case acquirePLL: {
   258         instanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
   259         debug_only(owned++;)
   260         break;
   261       }
   262       case releaseAndNotifyPLL: {
   263         assert(owned > 0, "Don't have PLL");
   264         instanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
   265         debug_only(owned--;)
   266         break;
   267       }
   268       case empty:
   269       default: {
   270         guarantee(false,"Unexpected message in _buffer");
   271         break;
   272       }
   273     }
   274     {
   275       MutexLocker x(&_monitor);
   276       // Since we are a JavaThread, we can't be here at a safepoint.
   277       assert(!SafepointSynchronize::is_at_safepoint(),
   278              "SLT is a JavaThread");
   279       _buffer = empty;
   280       _monitor.notify();
   281     }
   282   }
   283   assert(!_monitor.owned_by_self(), "Should unlock before exit.");
   284 }
   287 // ===== STS Access From Outside CGCT =====
   289 void ConcurrentGCThread::stsYield(const char* id) {
   290   assert( Thread::current()->is_ConcurrentGC_thread(),
   291           "only a conc GC thread can call this" );
   292   _sts.yield(id);
   293 }
   295 bool ConcurrentGCThread::stsShouldYield() {
   296   assert( Thread::current()->is_ConcurrentGC_thread(),
   297           "only a conc GC thread can call this" );
   298   return _sts.should_yield();
   299 }
   301 void ConcurrentGCThread::stsJoin() {
   302   assert( Thread::current()->is_ConcurrentGC_thread(),
   303           "only a conc GC thread can call this" );
   304   _sts.join();
   305 }
   307 void ConcurrentGCThread::stsLeave() {
   308   assert( Thread::current()->is_ConcurrentGC_thread(),
   309           "only a conc GC thread can call this" );
   310   _sts.leave();
   311 }

mercurial