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

Fri, 01 Oct 2010 16:43:05 -0400

author
tonyp
date
Fri, 01 Oct 2010 16:43:05 -0400
changeset 2197
6e0aac35bfa9
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
permissions
-rw-r--r--

6980838: G1: guarantee(false) failed: thread has an unexpected active value in its SATB queue
Summary: Under certain circumstances a safepoint could happen between a JavaThread object being created and that object being added to the Java threads list. This could cause the active field of that thread's SATB queue to get out-of-sync with respect to the other Java threads. The solution is to activate the SATB queue, when necessary, before adding the thread to the Java threads list, not when the JavaThread object is created. The changeset also includes a small fix to rename the surrogate locker thread from "Surrogate Locker Thread (CMS)" to "Surrogate Locker Thread (Concurrent GC)" since it's also used in G1.
Reviewed-by: iveresov, ysr, johnc, jcoomes

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

mercurial