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

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 // CopyrightVersion 1.2
ysr@777 26
ysr@777 27 # include "incls/_precompiled.incl"
ysr@777 28 # include "incls/_concurrentGCThread.cpp.incl"
ysr@777 29
ysr@777 30 int ConcurrentGCThread::_CGC_flag = CGC_nil;
ysr@777 31
ysr@777 32 SuspendibleThreadSet ConcurrentGCThread::_sts;
ysr@777 33
iveresov@1229 34 ConcurrentGCThread::ConcurrentGCThread() :
iveresov@1229 35 _should_terminate(false), _has_terminated(false) {
ysr@777 36 _sts.initialize();
ysr@777 37 };
ysr@777 38
ysr@777 39 void ConcurrentGCThread::stopWorldAndDo(VoidClosure* op) {
ysr@777 40 MutexLockerEx x(Heap_lock,
ysr@777 41 Mutex::_no_safepoint_check_flag);
ysr@777 42 // warning("CGC: about to try stopping world");
ysr@777 43 SafepointSynchronize::begin();
ysr@777 44 // warning("CGC: successfully stopped world");
ysr@777 45 op->do_void();
ysr@777 46 SafepointSynchronize::end();
ysr@777 47 // warning("CGC: successfully restarted world");
ysr@777 48 }
ysr@777 49
ysr@777 50 void ConcurrentGCThread::safepoint_synchronize() {
ysr@777 51 _sts.suspend_all();
ysr@777 52 }
ysr@777 53
ysr@777 54 void ConcurrentGCThread::safepoint_desynchronize() {
ysr@777 55 _sts.resume_all();
ysr@777 56 }
ysr@777 57
ysr@777 58 void ConcurrentGCThread::create_and_start() {
ysr@777 59 if (os::create_thread(this, os::cgc_thread)) {
ysr@777 60 // XXX: need to set this to low priority
ysr@777 61 // unless "agressive mode" set; priority
ysr@777 62 // should be just less than that of VMThread.
ysr@777 63 os::set_priority(this, NearMaxPriority);
ysr@777 64 if (!_should_terminate && !DisableStartThread) {
ysr@777 65 os::start_thread(this);
ysr@777 66 }
ysr@777 67 }
ysr@777 68 }
ysr@777 69
ysr@777 70 void ConcurrentGCThread::initialize_in_thread() {
ysr@777 71 this->record_stack_base_and_size();
ysr@777 72 this->initialize_thread_local_storage();
ysr@777 73 this->set_active_handles(JNIHandleBlock::allocate_block());
ysr@777 74 // From this time Thread::current() should be working.
ysr@777 75 assert(this == Thread::current(), "just checking");
ysr@777 76 }
ysr@777 77
ysr@777 78 void ConcurrentGCThread::wait_for_universe_init() {
ysr@777 79 MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
ysr@777 80 while (!is_init_completed() && !_should_terminate) {
ysr@777 81 CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200);
ysr@777 82 }
ysr@777 83 }
ysr@777 84
ysr@777 85 void ConcurrentGCThread::terminate() {
ysr@777 86 // Signal that it is terminated
ysr@777 87 {
ysr@777 88 MutexLockerEx mu(Terminator_lock,
ysr@777 89 Mutex::_no_safepoint_check_flag);
ysr@777 90 _has_terminated = true;
ysr@777 91 Terminator_lock->notify();
ysr@777 92 }
ysr@777 93
ysr@777 94 // Thread destructor usually does this..
ysr@777 95 ThreadLocalStorage::set_thread(NULL);
ysr@777 96 }
ysr@777 97
ysr@777 98
ysr@777 99 void SuspendibleThreadSet::initialize_work() {
ysr@777 100 MutexLocker x(STS_init_lock);
ysr@777 101 if (!_initialized) {
ysr@777 102 _m = new Monitor(Mutex::leaf,
ysr@777 103 "SuspendibleThreadSetLock", true);
ysr@777 104 _async = 0;
ysr@777 105 _async_stop = false;
ysr@777 106 _async_stopped = 0;
ysr@777 107 _initialized = true;
ysr@777 108 }
ysr@777 109 }
ysr@777 110
ysr@777 111 void SuspendibleThreadSet::join() {
ysr@777 112 initialize();
ysr@777 113 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
ysr@777 114 while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
ysr@777 115 _async++;
ysr@777 116 assert(_async > 0, "Huh.");
ysr@777 117 }
ysr@777 118
ysr@777 119 void SuspendibleThreadSet::leave() {
ysr@777 120 assert(_initialized, "Must be initialized.");
ysr@777 121 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
ysr@777 122 _async--;
ysr@777 123 assert(_async >= 0, "Huh.");
ysr@777 124 if (_async_stop) _m->notify_all();
ysr@777 125 }
ysr@777 126
ysr@777 127 void SuspendibleThreadSet::yield(const char* id) {
ysr@777 128 assert(_initialized, "Must be initialized.");
ysr@777 129 if (_async_stop) {
ysr@777 130 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
ysr@777 131 if (_async_stop) {
ysr@777 132 _async_stopped++;
ysr@777 133 assert(_async_stopped > 0, "Huh.");
ysr@777 134 if (_async_stopped == _async) {
ysr@777 135 if (ConcGCYieldTimeout > 0) {
ysr@777 136 double now = os::elapsedTime();
ysr@777 137 guarantee((now - _suspend_all_start) * 1000.0 <
ysr@777 138 (double)ConcGCYieldTimeout,
ysr@777 139 "Long delay; whodunit?");
ysr@777 140 }
ysr@777 141 }
ysr@777 142 _m->notify_all();
ysr@777 143 while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
ysr@777 144 _async_stopped--;
ysr@777 145 assert(_async >= 0, "Huh");
ysr@777 146 _m->notify_all();
ysr@777 147 }
ysr@777 148 }
ysr@777 149 }
ysr@777 150
ysr@777 151 void SuspendibleThreadSet::suspend_all() {
ysr@777 152 initialize(); // If necessary.
ysr@777 153 if (ConcGCYieldTimeout > 0) {
ysr@777 154 _suspend_all_start = os::elapsedTime();
ysr@777 155 }
ysr@777 156 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
ysr@777 157 assert(!_async_stop, "Only one at a time.");
ysr@777 158 _async_stop = true;
ysr@777 159 while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag);
ysr@777 160 }
ysr@777 161
ysr@777 162 void SuspendibleThreadSet::resume_all() {
ysr@777 163 assert(_initialized, "Must be initialized.");
ysr@777 164 MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
ysr@777 165 assert(_async_stopped == _async, "Huh.");
ysr@777 166 _async_stop = false;
ysr@777 167 _m->notify_all();
ysr@777 168 }
ysr@777 169
ysr@777 170 static void _sltLoop(JavaThread* thread, TRAPS) {
ysr@777 171 SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
ysr@777 172 slt->loop();
ysr@777 173 }
ysr@777 174
ysr@777 175 SurrogateLockerThread::SurrogateLockerThread() :
ysr@777 176 JavaThread(&_sltLoop),
ysr@777 177 _monitor(Mutex::nonleaf, "SLTMonitor"),
ysr@777 178 _buffer(empty)
ysr@777 179 {}
ysr@777 180
ysr@777 181 SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
ysr@777 182 klassOop k =
ysr@777 183 SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(),
ysr@777 184 true, CHECK_NULL);
ysr@777 185 instanceKlassHandle klass (THREAD, k);
ysr@777 186 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
ysr@777 187
tonyp@2197 188 const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)";
ysr@777 189 Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);
ysr@777 190
ysr@777 191 // Initialize thread_oop to put it into the system threadGroup
ysr@777 192 Handle thread_group (THREAD, Universe::system_thread_group());
ysr@777 193 JavaValue result(T_VOID);
ysr@777 194 JavaCalls::call_special(&result, thread_oop,
ysr@777 195 klass,
ysr@777 196 vmSymbolHandles::object_initializer_name(),
ysr@777 197 vmSymbolHandles::threadgroup_string_void_signature(),
ysr@777 198 thread_group,
ysr@777 199 string,
ysr@777 200 CHECK_NULL);
ysr@777 201
ysr@777 202 SurrogateLockerThread* res;
ysr@777 203 {
ysr@777 204 MutexLocker mu(Threads_lock);
ysr@777 205 res = new SurrogateLockerThread();
ysr@777 206
ysr@777 207 // At this point it may be possible that no osthread was created for the
ysr@777 208 // JavaThread due to lack of memory. We would have to throw an exception
ysr@777 209 // in that case. However, since this must work and we do not allow
ysr@777 210 // exceptions anyway, check and abort if this fails.
ysr@777 211 if (res == NULL || res->osthread() == NULL) {
ysr@777 212 vm_exit_during_initialization("java.lang.OutOfMemoryError",
ysr@777 213 "unable to create new native thread");
ysr@777 214 }
ysr@777 215 java_lang_Thread::set_thread(thread_oop(), res);
ysr@777 216 java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
ysr@777 217 java_lang_Thread::set_daemon(thread_oop());
ysr@777 218
ysr@777 219 res->set_threadObj(thread_oop());
ysr@777 220 Threads::add(res);
ysr@777 221 Thread::start(res);
ysr@777 222 }
ysr@777 223 os::yield(); // This seems to help with initial start-up of SLT
ysr@777 224 return res;
ysr@777 225 }
ysr@777 226
ysr@777 227 void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
ysr@777 228 MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
ysr@777 229 assert(_buffer == empty, "Should be empty");
ysr@777 230 assert(msg != empty, "empty message");
ysr@777 231 _buffer = msg;
ysr@777 232 while (_buffer != empty) {
ysr@777 233 _monitor.notify();
ysr@777 234 _monitor.wait(Mutex::_no_safepoint_check_flag);
ysr@777 235 }
ysr@777 236 }
ysr@777 237
ysr@777 238 // ======= Surrogate Locker Thread =============
ysr@777 239
ysr@777 240 void SurrogateLockerThread::loop() {
ysr@777 241 BasicLock pll_basic_lock;
ysr@777 242 SLT_msg_type msg;
ysr@777 243 debug_only(unsigned int owned = 0;)
ysr@777 244
ysr@777 245 while (/* !isTerminated() */ 1) {
ysr@777 246 {
ysr@777 247 MutexLocker x(&_monitor);
ysr@777 248 // Since we are a JavaThread, we can't be here at a safepoint.
ysr@777 249 assert(!SafepointSynchronize::is_at_safepoint(),
ysr@777 250 "SLT is a JavaThread");
ysr@777 251 // wait for msg buffer to become non-empty
ysr@777 252 while (_buffer == empty) {
ysr@777 253 _monitor.notify();
ysr@777 254 _monitor.wait();
ysr@777 255 }
ysr@777 256 msg = _buffer;
ysr@777 257 }
ysr@777 258 switch(msg) {
ysr@777 259 case acquirePLL: {
ysr@777 260 instanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
ysr@777 261 debug_only(owned++;)
ysr@777 262 break;
ysr@777 263 }
ysr@777 264 case releaseAndNotifyPLL: {
ysr@777 265 assert(owned > 0, "Don't have PLL");
ysr@777 266 instanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
ysr@777 267 debug_only(owned--;)
ysr@777 268 break;
ysr@777 269 }
ysr@777 270 case empty:
ysr@777 271 default: {
ysr@777 272 guarantee(false,"Unexpected message in _buffer");
ysr@777 273 break;
ysr@777 274 }
ysr@777 275 }
ysr@777 276 {
ysr@777 277 MutexLocker x(&_monitor);
ysr@777 278 // Since we are a JavaThread, we can't be here at a safepoint.
ysr@777 279 assert(!SafepointSynchronize::is_at_safepoint(),
ysr@777 280 "SLT is a JavaThread");
ysr@777 281 _buffer = empty;
ysr@777 282 _monitor.notify();
ysr@777 283 }
ysr@777 284 }
ysr@777 285 assert(!_monitor.owned_by_self(), "Should unlock before exit.");
ysr@777 286 }
ysr@777 287
ysr@777 288
ysr@777 289 // ===== STS Access From Outside CGCT =====
ysr@777 290
ysr@777 291 void ConcurrentGCThread::stsYield(const char* id) {
ysr@777 292 assert( Thread::current()->is_ConcurrentGC_thread(),
ysr@777 293 "only a conc GC thread can call this" );
ysr@777 294 _sts.yield(id);
ysr@777 295 }
ysr@777 296
ysr@777 297 bool ConcurrentGCThread::stsShouldYield() {
ysr@777 298 assert( Thread::current()->is_ConcurrentGC_thread(),
ysr@777 299 "only a conc GC thread can call this" );
ysr@777 300 return _sts.should_yield();
ysr@777 301 }
ysr@777 302
ysr@777 303 void ConcurrentGCThread::stsJoin() {
ysr@777 304 assert( Thread::current()->is_ConcurrentGC_thread(),
ysr@777 305 "only a conc GC thread can call this" );
ysr@777 306 _sts.join();
ysr@777 307 }
ysr@777 308
ysr@777 309 void ConcurrentGCThread::stsLeave() {
ysr@777 310 assert( Thread::current()->is_ConcurrentGC_thread(),
ysr@777 311 "only a conc GC thread can call this" );
ysr@777 312 _sts.leave();
ysr@777 313 }

mercurial