8151601: Cleanup locking of the Reference pending list
Reviewed-by: brutisso, stefank
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -130,7 +130,7 @@
virtualConstructor.addMapping("CodeCacheSweeperThread", CodeCacheSweeperThread.class);
}
// for now, use JavaThread itself. fix it later with appropriate class if needed
- virtualConstructor.addMapping("SurrogateLockerThread", JavaThread.class);
+ virtualConstructor.addMapping("ReferencePendingListLockerThread", JavaThread.class);
virtualConstructor.addMapping("JvmtiAgentThread", JvmtiAgentThread.class);
virtualConstructor.addMapping("ServiceThread", ServiceThread.class);
}
@@ -172,7 +172,7 @@
return thread;
} catch (Exception e) {
throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr +
- " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, SurrogateLockerThread, or CodeCacheSweeperThread)", e);
+ " (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, ReferencePendingListLockerThread, or CodeCacheSweeperThread)", e);
}
}
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -837,7 +837,7 @@
vmType2Class["JavaThread"] = sapkg.runtime.JavaThread;
vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread;
vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread;
-vmType2Class["SurrogateLockerThread"] = sapkg.runtime.JavaThread;
+vmType2Class["ReferencePendingListLockerThread"] = sapkg.runtime.JavaThread;
vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread;
// gc
--- a/hotspot/src/share/vm/ci/ciReplay.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciReplay.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,4 +1,5 @@
-/* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +29,7 @@
#include "ci/ciKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "compiler/compileBroker.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
@@ -574,7 +576,7 @@
Method* method = parse_method(CHECK);
if (had_error()) return;
/* just copied from Method, to build interpret data*/
- if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
+ if (ReferencePendingListLocker::is_locked_by_self()) {
return;
}
// To be properly initialized, some profiling in the MDO needs the
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
#include "compiler/compileLog.hpp"
#include "compiler/compilerOracle.hpp"
#include "compiler/directivesParser.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/methodData.hpp"
@@ -904,7 +905,7 @@
// the pending list lock or a 3-way deadlock may occur
// between the reference handler thread, a GC (instigated
// by a compiler thread), and compiled method registration.
- if (InstanceRefKlass::owns_pending_list_lock(JavaThread::current())) {
+ if (ReferencePendingListLocker::is_locked_by_self()) {
return;
}
@@ -1309,7 +1310,7 @@
* has been fulfilled?
*/
bool CompileBroker::is_compile_blocking() {
- assert(!InstanceRefKlass::owns_pending_list_lock(JavaThread::current()), "possible deadlock");
+ assert(!ReferencePendingListLocker::is_locked_by_self(), "possible deadlock");
return !BackgroundCompilation;
}
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -28,7 +28,7 @@
#include "gc/cms/concurrentMarkSweepThread.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/genCollectedHeap.hpp"
-#include "oops/instanceRefKlass.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
@@ -46,11 +46,6 @@
volatile jint ConcurrentMarkSweepThread::_pending_yields = 0;
-SurrogateLockerThread* ConcurrentMarkSweepThread::_slt = NULL;
-SurrogateLockerThread::SLT_msg_type
- ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty;
-Monitor* ConcurrentMarkSweepThread::_sltMonitor = NULL;
-
ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
: ConcurrentGCThread() {
assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
@@ -73,8 +68,6 @@
// That won't happen on Solaris for various reasons,
// but may well happen on non-Solaris platforms.
create_and_start(UseCriticalCMSThreadPriority ? CriticalPriority : NearMaxPriority);
-
- _sltMonitor = SLT_lock;
}
void ConcurrentMarkSweepThread::run_service() {
@@ -94,7 +87,7 @@
// We cannot start the SLT thread ourselves since we need
// to be a JavaThread to do so.
CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2);
- while (_slt == NULL && !should_terminate()) {
+ while (!ReferencePendingListLocker::is_initialized() && !should_terminate()) {
CGC_lock->wait(true, 200);
loopY.tick();
}
@@ -337,15 +330,3 @@
// and wait some more
}
}
-
-// Note: this method, although exported by the ConcurrentMarkSweepThread,
-// which is a non-JavaThread, can only be called by a JavaThread.
-// Currently this is done at vm creation time (post-vm-init) by the
-// main/Primordial (Java)Thread.
-// XXX Consider changing this in the future to allow the CMS thread
-// itself to create this thread?
-void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) {
- assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC");
- assert(_slt == NULL, "SLT already created");
- _slt = SurrogateLockerThread::make(THREAD);
-}
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepThread.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -39,11 +39,8 @@
friend class CMSCollector;
private:
- static ConcurrentMarkSweepThread* _cmst;
- static CMSCollector* _collector;
- static SurrogateLockerThread* _slt;
- static SurrogateLockerThread::SLT_msg_type _sltBuffer;
- static Monitor* _sltMonitor;
+ static ConcurrentMarkSweepThread* _cmst;
+ static CMSCollector* _collector;
enum CMS_flag_type {
CMS_nil = NoBits,
@@ -75,9 +72,6 @@
// Constructor
ConcurrentMarkSweepThread(CMSCollector* collector);
- static void makeSurrogateLockerThread(TRAPS);
- static SurrogateLockerThread* slt() { return _slt; }
-
static void threads_do(ThreadClosure* tc);
// Printing
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,21 +38,11 @@
// Methods in abstract class VM_CMS_Operation
//////////////////////////////////////////////////////////
void VM_CMS_Operation::acquire_pending_list_lock() {
- // The caller may block while communicating
- // with the SLT thread in order to acquire/release the PLL.
- SurrogateLockerThread* slt = ConcurrentMarkSweepThread::slt();
- if (slt != NULL) {
- slt->manipulatePLL(SurrogateLockerThread::acquirePLL);
- } else {
- SurrogateLockerThread::report_missing_slt();
- }
+ _pending_list_locker.lock();
}
void VM_CMS_Operation::release_and_notify_pending_list_lock() {
- // The caller may block while communicating
- // with the SLT thread in order to acquire/release the PLL.
- ConcurrentMarkSweepThread::slt()->
- manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
+ _pending_list_locker.unlock();
}
void VM_CMS_Operation::verify_before_gc() {
@@ -95,7 +85,7 @@
assert(!ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"Possible deadlock");
- if (needs_pll()) {
+ if (needs_pending_list_lock()) {
acquire_pending_list_lock();
}
// Get the Heap_lock after the pending_list_lock.
@@ -103,7 +93,7 @@
if (lost_race()) {
assert(_prologue_succeeded == false, "Initialized in c'tor");
Heap_lock->unlock();
- if (needs_pll()) {
+ if (needs_pending_list_lock()) {
release_and_notify_pending_list_lock();
}
} else {
@@ -120,7 +110,7 @@
// Release the Heap_lock first.
Heap_lock->unlock();
- if (needs_pll()) {
+ if (needs_pending_list_lock()) {
release_and_notify_pending_list_lock();
}
}
--- a/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/vmCMSOperations.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
#include "gc/cms/concurrentMarkSweepGeneration.hpp"
#include "gc/shared/gcCause.hpp"
#include "gc/shared/gcId.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "gc/shared/vmGCOperations.hpp"
#include "runtime/vm_operations.hpp"
@@ -51,6 +52,9 @@
class CMSCollector;
class VM_CMS_Operation: public VM_Operation {
+ private:
+ ReferencePendingListLocker _pending_list_locker;
+
protected:
CMSCollector* _collector; // associated collector
bool _prologue_succeeded; // whether doit_prologue succeeded
@@ -73,7 +77,7 @@
virtual const CMSCollector::CollectorState legal_state() const = 0;
// Whether the pending list lock needs to be held
- virtual const bool needs_pll() const = 0;
+ virtual const bool needs_pending_list_lock() const = 0;
// Execute operations in the context of the caller,
// prior to execution of the vm operation itself.
@@ -105,7 +109,7 @@
return CMSCollector::InitialMarking;
}
- virtual const bool needs_pll() const {
+ virtual const bool needs_pending_list_lock() const {
return false;
}
};
@@ -122,7 +126,7 @@
return CMSCollector::FinalMarking;
}
- virtual const bool needs_pll() const {
+ virtual const bool needs_pending_list_lock() const {
return true;
}
};
--- a/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/cms/vmStructs_cms.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,14 +51,12 @@
declare_type(ConcurrentMarkSweepGeneration,CardGeneration) \
declare_type(CompactibleFreeListSpace, CompactibleSpace) \
declare_type(ConcurrentMarkSweepThread, NamedThread) \
- declare_type(SurrogateLockerThread, JavaThread) \
declare_toplevel_type(CMSCollector) \
declare_toplevel_type(CMSBitMap) \
declare_toplevel_type(FreeChunk) \
declare_toplevel_type(Metablock) \
declare_toplevel_type(ConcurrentMarkSweepThread*) \
declare_toplevel_type(ConcurrentMarkSweepGeneration*) \
- declare_toplevel_type(SurrogateLockerThread*) \
declare_toplevel_type(CompactibleFreeListSpace*) \
declare_toplevel_type(CMSCollector*) \
declare_toplevel_type(AFLBinaryTreeDictionary) \
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -41,9 +41,6 @@
// The CM thread is created when the G1 garbage collector is used
-SurrogateLockerThread*
- ConcurrentMarkThread::_slt = NULL;
-
ConcurrentMarkThread::ConcurrentMarkThread(G1ConcurrentMark* cm) :
ConcurrentGCThread(),
_cm(cm),
@@ -305,16 +302,3 @@
set_in_progress();
}
}
-
-// Note: As is the case with CMS - this method, although exported
-// by the ConcurrentMarkThread, which is a non-JavaThread, can only
-// be called by a JavaThread. Currently this is done at vm creation
-// time (post-vm-init) by the main/Primordial (Java)Thread.
-// XXX Consider changing this in the future to allow the CM thread
-// itself to create this thread?
-void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
- assert(UseG1GC, "SLT thread needed only for concurrent GC");
- assert(THREAD->is_Java_thread(), "must be a Java thread");
- assert(_slt == NULL, "SLT already created");
- _slt = SurrogateLockerThread::make(THREAD);
-}
--- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -56,15 +56,10 @@
void run_service();
void stop_service();
- static SurrogateLockerThread* _slt;
-
public:
// Constructor
ConcurrentMarkThread(G1ConcurrentMark* cm);
- static void makeSurrogateLockerThread(TRAPS);
- static SurrogateLockerThread* slt() { return _slt; }
-
// Total virtual time so far for this thread and concurrent marking tasks.
double vtime_accum();
// Marking virtual time so far this thread and concurrent marking tasks.
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -1292,6 +1292,12 @@
return true;
}
+ // The reference pending list lock is acquired from from the
+ // ConcurrentMarkThread.
+ virtual bool needs_reference_pending_list_locker_thread() const {
+ return true;
+ }
+
inline bool is_in_young(const oop obj);
virtual bool is_scavengable(const void* addr);
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -205,23 +205,11 @@
}
void VM_CGC_Operation::acquire_pending_list_lock() {
- assert(_needs_pll, "don't call this otherwise");
- // The caller may block while communicating
- // with the SLT thread in order to acquire/release the PLL.
- SurrogateLockerThread* slt = ConcurrentMarkThread::slt();
- if (slt != NULL) {
- slt->manipulatePLL(SurrogateLockerThread::acquirePLL);
- } else {
- SurrogateLockerThread::report_missing_slt();
- }
+ _pending_list_locker.lock();
}
void VM_CGC_Operation::release_and_notify_pending_list_lock() {
- assert(_needs_pll, "don't call this otherwise");
- // The caller may block while communicating
- // with the SLT thread in order to acquire/release the PLL.
- ConcurrentMarkThread::slt()->
- manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL);
+ _pending_list_locker.unlock();
}
void VM_CGC_Operation::doit() {
@@ -236,10 +224,9 @@
bool VM_CGC_Operation::doit_prologue() {
// Note the relative order of the locks must match that in
// VM_GC_Operation::doit_prologue() or deadlocks can occur
- if (_needs_pll) {
+ if (_needs_pending_list_lock) {
acquire_pending_list_lock();
}
-
Heap_lock->lock();
return true;
}
@@ -248,7 +235,7 @@
// Note the relative order of the unlocks must match that in
// VM_GC_Operation::doit_epilogue()
Heap_lock->unlock();
- if (_needs_pll) {
+ if (_needs_pending_list_lock) {
release_and_notify_pending_list_lock();
}
}
--- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include "gc/g1/g1AllocationContext.hpp"
#include "gc/shared/gcId.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "gc/shared/vmGCOperations.hpp"
// VM_operations for the G1 collector.
@@ -102,10 +103,11 @@
// Concurrent GC stop-the-world operations such as remark and cleanup;
// consider sharing these with CMS's counterparts.
class VM_CGC_Operation: public VM_Operation {
- VoidClosure* _cl;
- const char* _printGCMessage;
- bool _needs_pll;
- uint _gc_id;
+ VoidClosure* _cl;
+ const char* _printGCMessage;
+ bool _needs_pending_list_lock;
+ ReferencePendingListLocker _pending_list_locker;
+ uint _gc_id;
protected:
// java.lang.ref.Reference support
@@ -113,8 +115,8 @@
void release_and_notify_pending_list_lock();
public:
- VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pll)
- : _cl(cl), _printGCMessage(printGCMsg), _needs_pll(needs_pll), _gc_id(GCId::current()) { }
+ VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pending_list_lock)
+ : _cl(cl), _printGCMessage(printGCMsg), _needs_pending_list_lock(needs_pending_list_lock), _gc_id(GCId::current()) {}
virtual VMOp_Type type() const { return VMOp_CGC_Operation; }
virtual void doit();
virtual bool doit_prologue();
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -438,6 +438,12 @@
// remembered set.
virtual void flush_deferred_store_barrier(JavaThread* thread);
+ // Should return true if the reference pending list lock is
+ // acquired from non-Java threads, such as a concurrent GC thread.
+ virtual bool needs_reference_pending_list_locker_thread() const {
+ return false;
+ }
+
// Perform a collection of the heap; intended for use in implementing
// "System.gc". This probably implies as full a collection as the
// "CollectedHeap" supports.
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -102,131 +102,3 @@
}
}
}
-
-static void _sltLoop(JavaThread* thread, TRAPS) {
- SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
- slt->loop();
-}
-
-SurrogateLockerThread::SurrogateLockerThread() :
- JavaThread(&_sltLoop),
- _monitor(Mutex::nonleaf, "SLTMonitor", false,
- Monitor::_safepoint_check_sometimes),
- _buffer(empty)
-{}
-
-SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
- Klass* k =
- SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
- true, CHECK_NULL);
- instanceKlassHandle klass (THREAD, k);
- instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
-
- 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
- Handle thread_group (THREAD, Universe::system_thread_group());
- JavaValue result(T_VOID);
- JavaCalls::call_special(&result, thread_oop,
- klass,
- vmSymbols::object_initializer_name(),
- vmSymbols::threadgroup_string_void_signature(),
- thread_group,
- string,
- CHECK_NULL);
-
- SurrogateLockerThread* res;
- {
- MutexLocker mu(Threads_lock);
- res = new SurrogateLockerThread();
-
- // At this point it may be possible that no osthread was created for the
- // JavaThread due to lack of memory. We would have to throw an exception
- // in that case. However, since this must work and we do not allow
- // exceptions anyway, check and abort if this fails.
- if (res == NULL || res->osthread() == NULL) {
- vm_exit_during_initialization("java.lang.OutOfMemoryError",
- os::native_thread_creation_failed_msg());
- }
- java_lang_Thread::set_thread(thread_oop(), res);
- java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
- java_lang_Thread::set_daemon(thread_oop());
-
- res->set_threadObj(thread_oop());
- Threads::add(res);
- Thread::start(res);
- }
- os::naked_yield(); // This seems to help with initial start-up of SLT
- return res;
-}
-
-void SurrogateLockerThread::report_missing_slt() {
- vm_exit_during_initialization(
- "GC before GC support fully initialized: "
- "SLT is needed but has not yet been created.");
- ShouldNotReachHere();
-}
-
-void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
- MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
- assert(_buffer == empty, "Should be empty");
- assert(msg != empty, "empty message");
- assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread");
-
- _buffer = msg;
- while (_buffer != empty) {
- _monitor.notify();
- _monitor.wait(Mutex::_no_safepoint_check_flag);
- }
-}
-
-// ======= Surrogate Locker Thread =============
-
-void SurrogateLockerThread::loop() {
- BasicLock pll_basic_lock;
- SLT_msg_type msg;
- debug_only(unsigned int owned = 0;)
-
- while (/* !isTerminated() */ 1) {
- {
- MutexLocker x(&_monitor);
- // Since we are a JavaThread, we can't be here at a safepoint.
- assert(!SafepointSynchronize::is_at_safepoint(),
- "SLT is a JavaThread");
- // wait for msg buffer to become non-empty
- while (_buffer == empty) {
- _monitor.notify();
- _monitor.wait();
- }
- msg = _buffer;
- }
- switch(msg) {
- case acquirePLL: {
- InstanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
- debug_only(owned++;)
- break;
- }
- case releaseAndNotifyPLL: {
- assert(owned > 0, "Don't have PLL");
- InstanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
- debug_only(owned--;)
- break;
- }
- case empty:
- default: {
- guarantee(false,"Unexpected message in _buffer");
- break;
- }
- }
- {
- MutexLocker x(&_monitor);
- // Since we are a JavaThread, we can't be here at a safepoint.
- assert(!SafepointSynchronize::is_at_safepoint(),
- "SLT is a JavaThread");
- _buffer = empty;
- _monitor.notify();
- }
- }
- assert(!_monitor.owned_by_self(), "Should unlock before exit.");
-}
--- a/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/concurrentGCThread.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -70,37 +70,4 @@
bool has_terminated() { return _has_terminated; }
};
-// The SurrogateLockerThread is used by concurrent GC threads for
-// manipulating Java monitors, in particular, currently for
-// manipulating the pending_list_lock. XXX
-class SurrogateLockerThread: public JavaThread {
- friend class VMStructs;
- public:
- enum SLT_msg_type {
- empty = 0, // no message
- acquirePLL, // acquire pending list lock
- releaseAndNotifyPLL // notify and release pending list lock
- };
- private:
- // the following are shared with the CMSThread
- SLT_msg_type _buffer; // communication buffer
- Monitor _monitor; // monitor controlling buffer
- BasicLock _basicLock; // used for PLL locking
-
- public:
- static SurrogateLockerThread* make(TRAPS);
-
- // Terminate VM with error message that SLT needed but not yet created.
- static void report_missing_slt();
-
- SurrogateLockerThread();
-
- bool is_hidden_from_external_view() const { return true; }
-
- void loop(); // main method
-
- void manipulatePLL(SLT_msg_type msg);
-
-};
-
#endif // SHARE_VM_GC_SHARED_CONCURRENTGCTHREAD_HPP
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -281,6 +281,10 @@
return UseConcMarkSweepGC;
}
+ virtual bool needs_reference_pending_list_locker_thread() const {
+ return UseConcMarkSweepGC;
+ }
+
// We don't need barriers for stores to objects in the
// young gen and, a fortiori, for initializing stores to
// objects therein. This applies to DefNew+Tenured and ParNew+CMS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/javaClasses.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
+#include "memory/universe.hpp"
+#include "runtime/javaCalls.hpp"
+#include "utilities/preserveException.hpp"
+
+ReferencePendingListLockerThread::ReferencePendingListLockerThread() :
+ JavaThread(&start),
+ _monitor(Monitor::nonleaf, "ReferencePendingListLocker", false, Monitor::_safepoint_check_sometimes),
+ _message(NONE) {}
+
+ReferencePendingListLockerThread* ReferencePendingListLockerThread::create(TRAPS) {
+ // Create Java thread objects
+ instanceKlassHandle thread_klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_NULL);
+ instanceHandle thread_object = thread_klass->allocate_instance_handle(CHECK_NULL);
+ Handle thread_name = java_lang_String::create_from_str("Reference Pending List Locker", CHECK_NULL);
+ Handle thread_group = Universe::system_thread_group();
+ JavaValue result(T_VOID);
+ JavaCalls::call_special(&result,
+ thread_object,
+ thread_klass,
+ vmSymbols::object_initializer_name(),
+ vmSymbols::threadgroup_string_void_signature(),
+ thread_group,
+ thread_name,
+ CHECK_NULL);
+
+ {
+ MutexLocker ml(Threads_lock);
+
+ // Allocate thread
+ ReferencePendingListLockerThread* thread = new ReferencePendingListLockerThread();
+ if (thread == NULL || thread->osthread() == NULL) {
+ vm_exit_during_initialization("java.lang.OutOfMemoryError",
+ os::native_thread_creation_failed_msg());
+ }
+
+ // Initialize thread
+ java_lang_Thread::set_thread(thread_object(), thread);
+ java_lang_Thread::set_priority(thread_object(), NearMaxPriority);
+ java_lang_Thread::set_daemon(thread_object());
+ thread->set_threadObj(thread_object());
+
+ // Start thread
+ Threads::add(thread);
+ Thread::start(thread);
+
+ return thread;
+ }
+}
+
+void ReferencePendingListLockerThread::start(JavaThread* thread, TRAPS) {
+ ReferencePendingListLockerThread* locker_thread = static_cast<ReferencePendingListLockerThread*>(thread);
+ locker_thread->receive_and_handle_messages();
+}
+
+bool ReferencePendingListLockerThread::is_hidden_from_external_view() const {
+ return true;
+}
+
+void ReferencePendingListLockerThread::send_message(Message message) {
+ assert(message != NONE, "Should not be none");
+ MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+
+ // Wait for completion of current message
+ while (_message != NONE) {
+ ml.wait(Monitor::_no_safepoint_check_flag);
+ }
+
+ // Send new message
+ _message = message;
+ ml.notify_all();
+
+ // Wait for completion of new message
+ while (_message != NONE) {
+ ml.wait(Monitor::_no_safepoint_check_flag);
+ }
+}
+
+void ReferencePendingListLockerThread::receive_and_handle_messages() {
+ ReferencePendingListLocker pending_list_locker;
+ MonitorLockerEx ml(&_monitor);
+
+ // Main loop, never terminates
+ for (;;) {
+ // Wait for message
+ while (_message == NONE) {
+ ml.wait();
+ }
+
+ // Handle message
+ if (_message == LOCK) {
+ pending_list_locker.lock();
+ } else if (_message == UNLOCK) {
+ pending_list_locker.unlock();
+ } else {
+ ShouldNotReachHere();
+ }
+
+ // Clear message
+ _message = NONE;
+ ml.notify_all();
+ }
+}
+
+void ReferencePendingListLockerThread::lock() {
+ send_message(LOCK);
+}
+
+void ReferencePendingListLockerThread::unlock() {
+ send_message(UNLOCK);
+}
+
+bool ReferencePendingListLocker::_is_initialized = false;
+ReferencePendingListLockerThread* ReferencePendingListLocker::_locker_thread = NULL;
+
+void ReferencePendingListLocker::initialize(bool needs_locker_thread, TRAPS) {
+ if (needs_locker_thread) {
+ _locker_thread = ReferencePendingListLockerThread::create(CHECK);
+ }
+
+ _is_initialized = true;
+}
+
+bool ReferencePendingListLocker::is_initialized() {
+ return _is_initialized;
+}
+
+bool ReferencePendingListLocker::is_locked_by_self() {
+ oop pending_list_lock = java_lang_ref_Reference::pending_list_lock();
+ if (pending_list_lock == NULL) {
+ return false;
+ }
+
+ JavaThread* thread = JavaThread::current();
+ Handle handle(thread, pending_list_lock);
+ return ObjectSynchronizer::current_thread_holds_lock(thread, handle);
+}
+
+void ReferencePendingListLocker::lock() {
+ assert(!Heap_lock->owned_by_self(), "Heap_lock must not be owned by requesting thread");
+
+ if (Thread::current()->is_Java_thread()) {
+ assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized");
+
+ // We may enter this with a pending exception
+ PRESERVE_EXCEPTION_MARK;
+
+ HandleMark hm;
+ Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock());
+
+ assert(!is_locked_by_self(), "Should not be locked by self");
+
+ // Lock
+ ObjectSynchronizer::fast_enter(handle, &_basic_lock, false, THREAD);
+
+ assert(is_locked_by_self(), "Locking failed");
+
+ if (HAS_PENDING_EXCEPTION) {
+ CLEAR_PENDING_EXCEPTION;
+ }
+ } else {
+ // Delegate operation to locker thread
+ assert(_locker_thread != NULL, "Locker thread not created");
+ _locker_thread->lock();
+ }
+}
+
+void ReferencePendingListLocker::unlock() {
+ if (Thread::current()->is_Java_thread()) {
+ assert(java_lang_ref_Reference::pending_list_lock() != NULL, "Not initialized");
+
+ // We may enter this with a pending exception
+ PRESERVE_EXCEPTION_MARK;
+
+ HandleMark hm;
+ Handle handle(THREAD, java_lang_ref_Reference::pending_list_lock());
+
+ assert(is_locked_by_self(), "Should be locked by self");
+
+ // Notify waiters if the pending list is non-empty
+ if (java_lang_ref_Reference::pending_list() != NULL) {
+ ObjectSynchronizer::notifyall(handle, THREAD);
+ }
+
+ // Unlock
+ ObjectSynchronizer::fast_exit(handle(), &_basic_lock, THREAD);
+
+ assert(!is_locked_by_self(), "Unlocking failed");
+
+ if (HAS_PENDING_EXCEPTION) {
+ CLEAR_PENDING_EXCEPTION;
+ }
+ } else {
+ // Delegate operation to locker thread
+ assert(_locker_thread != NULL, "Locker thread not created");
+ _locker_thread->unlock();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/shared/referencePendingListLocker.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
+#define SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/basicLock.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/exceptions.hpp"
+
+//
+// The ReferencePendingListLockerThread locks and unlocks the reference
+// pending list lock on behalf a non-Java thread, typically a concurrent
+// GC thread. This interface should not be directly accessed. All uses
+// should instead go through the ReferencePendingListLocker, which calls
+// this thread if needed.
+//
+class ReferencePendingListLockerThread : public JavaThread {
+private:
+ enum Message {
+ NONE,
+ LOCK,
+ UNLOCK
+ };
+
+ Monitor _monitor;
+ Message _message;
+
+ ReferencePendingListLockerThread();
+
+ static void start(JavaThread* thread, TRAPS);
+
+ void send_message(Message message);
+ void receive_and_handle_messages();
+
+public:
+ static ReferencePendingListLockerThread* create(TRAPS);
+
+ virtual bool is_hidden_from_external_view() const;
+
+ void lock();
+ void unlock();
+};
+
+//
+// The ReferencePendingListLocker is the main interface for locking and
+// unlocking the reference pending list lock, which needs to be held by
+// the GC when adding references to the pending list. Since this is a
+// Java-level monitor it can only be locked/unlocked by a Java thread.
+// For this reason there is an option to spawn a helper thread, the
+// ReferencePendingListLockerThread, during initialization. If a helper
+// thread is spawned all lock operations from non-Java threads will be
+// delegated to the helper thread. The helper thread is typically needed
+// by concurrent GCs.
+//
+class ReferencePendingListLocker VALUE_OBJ_CLASS_SPEC {
+private:
+ static bool _is_initialized;
+ static ReferencePendingListLockerThread* _locker_thread;
+ BasicLock _basic_lock;
+
+public:
+ static void initialize(bool needs_locker_thread, TRAPS);
+ static bool is_initialized();
+
+ static bool is_locked_by_self();
+
+ void lock();
+ void unlock();
+};
+
+#endif // SHARE_VM_GC_SHARED_REFERENCEPENDINGLISTLOCKER_HPP
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -30,10 +30,8 @@
#include "gc/shared/gcLocker.inline.hpp"
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/vmGCOperations.hpp"
+#include "logging/log.hpp"
#include "memory/oopFactory.hpp"
-#include "logging/log.hpp"
-#include "oops/instanceKlass.hpp"
-#include "oops/instanceRefKlass.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
@@ -64,14 +62,11 @@
}
void VM_GC_Operation::acquire_pending_list_lock() {
- // we may enter this with pending exception set
- InstanceRefKlass::acquire_pending_list_lock(&_pending_list_basic_lock);
+ _pending_list_locker.lock();
}
-
void VM_GC_Operation::release_and_notify_pending_list_lock() {
-
- InstanceRefKlass::release_and_notify_pending_list_lock(&_pending_list_basic_lock);
+ _pending_list_locker.unlock();
}
// Allocations may fail in several threads at about the same time,
--- a/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/gc/shared/vmGCOperations.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/genCollectedHeap.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "memory/heapInspection.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/handles.hpp"
@@ -69,8 +70,10 @@
//
class VM_GC_Operation: public VM_Operation {
+ private:
+ ReferencePendingListLocker _pending_list_locker;
+
protected:
- BasicLock _pending_list_basic_lock; // for refs pending list notification (PLL)
uint _gc_count_before; // gc count before acquiring PLL
uint _full_gc_count_before; // full gc count before acquiring PLL
bool _full; // whether a "full" collection
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,8 @@
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "oops/instanceRefKlass.inline.hpp"
#include "oops/oop.inline.hpp"
-#include "utilities/macros.hpp"
-#include "utilities/preserveException.hpp"
void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) {
// Clear the nonstatic oop-map entries corresponding to referent
@@ -87,48 +82,3 @@
guarantee(InstanceKlass::cast(next->klass())->is_reference_instance_klass(), "next field verify failed");
}
}
-
-bool InstanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
- if (java_lang_ref_Reference::pending_list_lock() == NULL) return false;
- Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
- return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
-}
-
-void InstanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
- // we may enter this with pending exception set
- PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument
-
- // Create a HandleMark in case we retry a GC multiple times.
- // Each time we attempt the GC, we allocate the handle below
- // to hold the pending list lock. We want to free this handle.
- HandleMark hm;
-
- Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
- ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
- assert(ObjectSynchronizer::current_thread_holds_lock(
- JavaThread::current(), h_lock),
- "Locking should have succeeded");
- if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
-}
-
-void InstanceRefKlass::release_and_notify_pending_list_lock(
- BasicLock *pending_list_basic_lock) {
- // we may enter this with pending exception set
- PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument
-
- // Create a HandleMark in case we retry a GC multiple times.
- // Each time we attempt the GC, we allocate the handle below
- // to hold the pending list lock. We want to free this handle.
- HandleMark hm;
-
- Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
- assert(ObjectSynchronizer::current_thread_holds_lock(
- JavaThread::current(), h_lock),
- "Lock should be held");
- // Notify waiters on pending lists lock if there is any reference.
- if (java_lang_ref_Reference::pending_list() != NULL) {
- ObjectSynchronizer::notifyall(h_lock, THREAD);
- }
- ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD);
- if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
-}
--- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -118,10 +118,6 @@
ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_BACKWARDS)
#endif // INCLUDE_ALL_GCS
- static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock);
- static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock);
- static bool owns_pending_list_lock(JavaThread* thread);
-
// Update non-static oop maps so 'referent', 'nextPending' and
// 'discovered' will look like non-oops
static void update_nonstatic_oop_maps(Klass* k);
--- a/hotspot/src/share/vm/oops/method.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/oops/method.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -30,6 +30,7 @@
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/generation.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/bytecodeTracer.hpp"
#include "interpreter/bytecodes.hpp"
@@ -374,7 +375,7 @@
// Do not profile method if current thread holds the pending list lock,
// which avoids deadlock for acquiring the MethodData_lock.
- if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
+ if (ReferencePendingListLocker::is_locked_by_self()) {
return;
}
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -70,7 +70,6 @@
Monitor* Threads_lock = NULL;
Monitor* CGC_lock = NULL;
Monitor* STS_lock = NULL;
-Monitor* SLT_lock = NULL;
Monitor* FullGCCount_lock = NULL;
Mutex* SATB_Q_FL_lock = NULL;
Monitor* SATB_Q_CBL_mon = NULL;
@@ -242,9 +241,6 @@
def(JNIGlobalHandle_lock , Mutex , nonleaf, true, Monitor::_safepoint_check_always); // locks JNIHandleBlockFreeList_lock
def(JNICritical_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_always); // used for JNI critical regions
def(AdapterHandlerLibrary_lock , Mutex , nonleaf, true, Monitor::_safepoint_check_always);
- if (UseConcMarkSweepGC) {
- def(SLT_lock , Monitor, nonleaf, false, Monitor::_safepoint_check_never); // used in CMS GC for locking PLL lock
- }
def(Heap_lock , Monitor, nonleaf+1, false, Monitor::_safepoint_check_sometimes);
def(JfieldIdCreation_lock , Mutex , nonleaf+1, true, Monitor::_safepoint_check_always); // jfieldID, Used in VM_Operation
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Mar 17 08:07:53 2016 +0100
@@ -65,7 +65,6 @@
extern Monitor* CGC_lock; // used for coordination between
// fore- & background GC threads.
extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet.
-extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL
extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc
extern Mutex* SATB_Q_FL_lock; // Protects SATB Q
// buffer free list.
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/thread.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -34,6 +34,7 @@
#include "compiler/compileTask.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/shared/gcLocker.inline.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "gc/shared/workgroup.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
@@ -3650,18 +3651,9 @@
// anymore. We call vm_exit_during_initialization directly instead.
SystemDictionary::compute_java_system_loader(CHECK_(JNI_ERR));
-#if INCLUDE_ALL_GCS
- // Support for ConcurrentMarkSweep. This should be cleaned up
- // and better encapsulated. The ugly nested if test would go away
- // once things are properly refactored. XXX YSR
- if (UseConcMarkSweepGC || UseG1GC) {
- if (UseConcMarkSweepGC) {
- ConcurrentMarkSweepThread::makeSurrogateLockerThread(CHECK_JNI_ERR);
- } else {
- ConcurrentMarkThread::makeSurrogateLockerThread(CHECK_JNI_ERR);
- }
- }
-#endif // INCLUDE_ALL_GCS
+ // Initialize reference pending list locker
+ bool needs_locker_thread = Universe::heap()->needs_reference_pending_list_locker_thread();
+ ReferencePendingListLocker::initialize(needs_locker_thread, CHECK_JNI_ERR);
// Always call even when there are not JVMTI environments yet, since environments
// may be attached late and JVMTI must track phases of VM execution
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Mar 16 16:21:36 2016 +0000
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Mar 17 08:07:53 2016 +0100
@@ -54,6 +54,7 @@
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/generation.hpp"
#include "gc/shared/generationSpec.hpp"
+#include "gc/shared/referencePendingListLocker.hpp"
#include "gc/shared/space.hpp"
#include "interpreter/bytecodeInterpreter.hpp"
#include "interpreter/bytecodes.hpp"
@@ -1692,6 +1693,7 @@
declare_type(JavaThread, Thread) \
declare_type(JvmtiAgentThread, JavaThread) \
declare_type(ServiceThread, JavaThread) \
+ declare_type(ReferencePendingListLockerThread, JavaThread) \
declare_type(CompilerThread, JavaThread) \
declare_type(CodeCacheSweeperThread, JavaThread) \
declare_toplevel_type(OSThread) \