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

Thu, 20 Sep 2012 09:52:56 -0700

author
johnc
date
Thu, 20 Sep 2012 09:52:56 -0700
changeset 4067
b2ef234911c9
parent 4047
aed758eda82a
child 6876
710a3c8b516e
child 6906
581e70386ec9
permissions
-rw-r--r--

7190666: G1: assert(_unused == 0) failed: Inconsistency in PLAB stats
Summary: Reset the fields in ParGCAllocBuffer, that are used for accumulating values for the ResizePLAB sensors in PLABStats, to zero after flushing the values to the PLABStats fields. Flush PLABStats values only when retiring the final allocation buffers prior to disposing of a G1ParScanThreadState object, rather than when retiring every allocation buffer.
Reviewed-by: jwilhelm, jmasa, ysr

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

mercurial