diff --git a/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp b/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp index 524c0c25681fcff0902cc81cd202e051b05e9e9e..9f6d95f00a209356148efcfb4c42a0c9de0cbad1 100644 --- a/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp +++ b/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp @@ -37,11 +37,10 @@ public: class DirtyCardQueue: public PtrQueue { public: DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) : - PtrQueue(qset_, perm) - { - // Dirty card queues are always active. - _active = true; - } + // Dirty card queues are always active, so we create them with their + // active field set to true. + PtrQueue(qset_, perm, true /* active */) { } + // Apply the closure to all elements, and reset the index to make the // buffer empty. If a closure application returns "false", return // "false" immediately, halting the iteration. If "consume" is true, diff --git a/src/share/vm/gc_implementation/g1/ptrQueue.hpp b/src/share/vm/gc_implementation/g1/ptrQueue.hpp index bbd4788e89ffaf879b4f57ea8d7c63a5e82e4d47..c66973b0cad519d2d550e2ee0e0be6488b64181d 100644 --- a/src/share/vm/gc_implementation/g1/ptrQueue.hpp +++ b/src/share/vm/gc_implementation/g1/ptrQueue.hpp @@ -89,6 +89,10 @@ public: return _buf == NULL ? 0 : _sz - _index; } + bool is_empty() { + return _buf == NULL || _sz == _index; + } + // Set the "active" property of the queue to "b". An enqueue to an // inactive thread is a no-op. Setting a queue to inactive resets its // log to the empty state. diff --git a/src/share/vm/gc_implementation/g1/satbQueue.hpp b/src/share/vm/gc_implementation/g1/satbQueue.hpp index 49f824463e9acd5533017d97706ea6e6c984a327..6a1f50e2b3169fdb674c19819bb3a49bf9da73a7 100644 --- a/src/share/vm/gc_implementation/g1/satbQueue.hpp +++ b/src/share/vm/gc_implementation/g1/satbQueue.hpp @@ -29,7 +29,12 @@ class JavaThread; class ObjPtrQueue: public PtrQueue { public: ObjPtrQueue(PtrQueueSet* qset_, bool perm = false) : - PtrQueue(qset_, perm, qset_->is_active()) { } + // SATB queues are only active during marking cycles. We create + // them with their active field set to false. If a thread is + // created during a cycle and its SATB queue needs to be activated + // before the thread starts running, we'll need to set its active + // field to true. This is done in JavaThread::initialize_queues(). + PtrQueue(qset_, perm, false /* active */) { } // Apply the closure to all elements, and reset the index to make the // buffer empty. void apply_closure(ObjectClosure* cl); diff --git a/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp b/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp index 65643f818b50631f77972886b9913c36031a5e46..6b81ed95f1bea6e2b33738cc965b93253f0b4039 100644 --- a/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp +++ b/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp @@ -185,7 +185,7 @@ SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) { instanceKlassHandle klass (THREAD, k); instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL); - const char thread_name[] = "Surrogate Locker Thread (CMS)"; + const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)"; Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL); // Initialize thread_oop to put it into the system threadGroup diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp index 00e5e991efcec10f063f6f35600f6f362469e1ad..89a710d45ac51a9c95429c557fecba039b07f5a9 100644 --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -1644,7 +1644,29 @@ void JavaThread::flush_barrier_queues() { satb_mark_queue().flush(); dirty_card_queue().flush(); } -#endif + +void JavaThread::initialize_queues() { + assert(!SafepointSynchronize::is_at_safepoint(), + "we should not be at a safepoint"); + + ObjPtrQueue& satb_queue = satb_mark_queue(); + SATBMarkQueueSet& satb_queue_set = satb_mark_queue_set(); + // The SATB queue should have been constructed with its active + // field set to false. + assert(!satb_queue.is_active(), "SATB queue should not be active"); + assert(satb_queue.is_empty(), "SATB queue should be empty"); + // If we are creating the thread during a marking cycle, we should + // set the active field of the SATB queue to true. + if (satb_queue_set.is_active()) { + satb_queue.set_active(true); + } + + DirtyCardQueue& dirty_queue = dirty_card_queue(); + // The dirty card queue should have been constructed with its + // active field set to true. + assert(dirty_queue.is_active(), "dirty card queue should be active"); +} +#endif // !SERIALGC void JavaThread::cleanup_failed_attach_current_thread() { if (get_thread_profiler() != NULL) { @@ -3626,6 +3648,10 @@ jboolean Threads::is_supported_jni_version(jint version) { void Threads::add(JavaThread* p, bool force_daemon) { // The threads lock must be owned at this point assert_locked_or_safepoint(Threads_lock); + + // See the comment for this method in thread.hpp for its purpose and + // why it is called here. + p->initialize_queues(); p->set_next(_thread_list); _thread_list = p; _number_of_threads++; diff --git a/src/share/vm/runtime/thread.hpp b/src/share/vm/runtime/thread.hpp index 61237f41323495ba56a5120b5cf3f92af19682e7..4a7f650c23219adc846de0ccbad29d2034faee48 100644 --- a/src/share/vm/runtime/thread.hpp +++ b/src/share/vm/runtime/thread.hpp @@ -1487,6 +1487,29 @@ public: } #endif // !SERIALGC + // This method initializes the SATB and dirty card queues before a + // JavaThread is added to the Java thread list. Right now, we don't + // have to do anything to the dirty card queue (it should have been + // activated when the thread was created), but we have to activate + // the SATB queue if the thread is created while a marking cycle is + // in progress. The activation / de-activation of the SATB queues at + // the beginning / end of a marking cycle is done during safepoints + // so we have to make sure this method is called outside one to be + // able to safely read the active field of the SATB queue set. Right + // now, it is called just before the thread is added to the Java + // thread list in the Threads::add() method. That method is holding + // the Threads_lock which ensures we are outside a safepoint. We + // cannot do the obvious and set the active field of the SATB queue + // when the thread is created given that, in some cases, safepoints + // might happen between the JavaThread constructor being called and the + // thread being added to the Java thread list (an example of this is + // when the structure for the DestroyJavaVM thread is created). +#ifndef SERIALGC + void initialize_queues(); +#else // !SERIALGC + void initialize_queues() { } +#endif // !SERIALGC + // Machine dependent stuff #include "incls/_thread_pd.hpp.incl"