mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
6988353: refactor contended sync subsystem
Reduce complexity by factoring synchronizer.cpp Reviewed-by: dholmes, never, coleenp
This commit is contained in:
parent
daa052114f
commit
22929fb78f
29 changed files with 4556 additions and 4792 deletions
|
@ -22,6 +22,32 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
// ObjectWaiter serves as a "proxy" or surrogate thread.
|
||||
// TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific
|
||||
// ParkEvent instead. Beware, however, that the JVMTI code
|
||||
// knows about ObjectWaiters, so we'll have to reconcile that code.
|
||||
// See next_waiter(), first_waiter(), etc.
|
||||
|
||||
class ObjectWaiter : public StackObj {
|
||||
public:
|
||||
enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
|
||||
enum Sorted { PREPEND, APPEND, SORTED } ;
|
||||
ObjectWaiter * volatile _next;
|
||||
ObjectWaiter * volatile _prev;
|
||||
Thread* _thread;
|
||||
ParkEvent * _event;
|
||||
volatile int _notified ;
|
||||
volatile TStates TState ;
|
||||
Sorted _Sorted ; // List placement disposition
|
||||
bool _active ; // Contention monitoring is enabled
|
||||
public:
|
||||
ObjectWaiter(Thread* thread);
|
||||
|
||||
void wait_reenter_begin(ObjectMonitor *mon);
|
||||
void wait_reenter_end(ObjectMonitor *mon);
|
||||
};
|
||||
|
||||
// WARNING:
|
||||
// This is a very sensitive and fragile class. DO NOT make any
|
||||
// change unless you are fully aware of the underlying semantics.
|
||||
|
@ -38,8 +64,6 @@
|
|||
// It is also used as RawMonitor by the JVMTI
|
||||
|
||||
|
||||
class ObjectWaiter;
|
||||
|
||||
class ObjectMonitor {
|
||||
public:
|
||||
enum {
|
||||
|
@ -74,13 +98,16 @@ class ObjectMonitor {
|
|||
|
||||
|
||||
public:
|
||||
ObjectMonitor();
|
||||
~ObjectMonitor();
|
||||
|
||||
markOop header() const;
|
||||
void set_header(markOop hdr);
|
||||
|
||||
intptr_t is_busy() const;
|
||||
intptr_t is_busy() const {
|
||||
// TODO-FIXME: merge _count and _waiters.
|
||||
// TODO-FIXME: assert _owner == null implies _recursions = 0
|
||||
// TODO-FIXME: assert _WaitSet != null implies _count > 0
|
||||
return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ;
|
||||
}
|
||||
|
||||
intptr_t is_entered(Thread* current) const;
|
||||
|
||||
void* owner() const;
|
||||
|
@ -91,13 +118,58 @@ class ObjectMonitor {
|
|||
intptr_t count() const;
|
||||
void set_count(intptr_t count);
|
||||
intptr_t contentions() const ;
|
||||
intptr_t recursions() const { return _recursions; }
|
||||
|
||||
// JVM/DI GetMonitorInfo() needs this
|
||||
Thread * thread_of_waiter (ObjectWaiter *) ;
|
||||
ObjectWaiter * first_waiter () ;
|
||||
ObjectWaiter * next_waiter(ObjectWaiter* o);
|
||||
ObjectWaiter* first_waiter() { return _WaitSet; }
|
||||
ObjectWaiter* next_waiter(ObjectWaiter* o) { return o->_next; }
|
||||
Thread* thread_of_waiter(ObjectWaiter* o) { return o->_thread; }
|
||||
|
||||
intptr_t recursions() const { return _recursions; }
|
||||
// initialize the monitor, exception the semaphore, all other fields
|
||||
// are simple integers or pointers
|
||||
ObjectMonitor() {
|
||||
_header = NULL;
|
||||
_count = 0;
|
||||
_waiters = 0,
|
||||
_recursions = 0;
|
||||
_object = NULL;
|
||||
_owner = NULL;
|
||||
_WaitSet = NULL;
|
||||
_WaitSetLock = 0 ;
|
||||
_Responsible = NULL ;
|
||||
_succ = NULL ;
|
||||
_cxq = NULL ;
|
||||
FreeNext = NULL ;
|
||||
_EntryList = NULL ;
|
||||
_SpinFreq = 0 ;
|
||||
_SpinClock = 0 ;
|
||||
OwnerIsThread = 0 ;
|
||||
}
|
||||
|
||||
~ObjectMonitor() {
|
||||
// TODO: Add asserts ...
|
||||
// _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
|
||||
// _count == 0 _EntryList == NULL etc
|
||||
}
|
||||
|
||||
private:
|
||||
void Recycle () {
|
||||
// TODO: add stronger asserts ...
|
||||
// _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
|
||||
// _count == 0 EntryList == NULL
|
||||
// _recursions == 0 _WaitSet == NULL
|
||||
// TODO: assert (is_busy()|_recursions) == 0
|
||||
_succ = NULL ;
|
||||
_EntryList = NULL ;
|
||||
_cxq = NULL ;
|
||||
_WaitSet = NULL ;
|
||||
_recursions = 0 ;
|
||||
_SpinFreq = 0 ;
|
||||
_SpinClock = 0 ;
|
||||
OwnerIsThread = 0 ;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void* object() const;
|
||||
void* object_addr();
|
||||
|
@ -122,22 +194,9 @@ class ObjectMonitor {
|
|||
intptr_t complete_exit(TRAPS);
|
||||
void reenter(intptr_t recursions, TRAPS);
|
||||
|
||||
int raw_enter(TRAPS);
|
||||
int raw_exit(TRAPS);
|
||||
int raw_wait(jlong millis, bool interruptable, TRAPS);
|
||||
int raw_notify(TRAPS);
|
||||
int raw_notifyAll(TRAPS);
|
||||
|
||||
private:
|
||||
// JVMTI support -- remove ASAP
|
||||
int SimpleEnter (Thread * Self) ;
|
||||
int SimpleExit (Thread * Self) ;
|
||||
int SimpleWait (Thread * Self, jlong millis) ;
|
||||
int SimpleNotify (Thread * Self, bool All) ;
|
||||
|
||||
private:
|
||||
void Recycle () ;
|
||||
void AddWaiter (ObjectWaiter * waiter) ;
|
||||
static void DeferredInitialize();
|
||||
|
||||
ObjectWaiter * DequeueWaiter () ;
|
||||
void DequeueSpecificWaiter (ObjectWaiter * waiter) ;
|
||||
|
@ -172,13 +231,17 @@ class ObjectMonitor {
|
|||
// The VM assumes write ordering wrt these fields, which can be
|
||||
// read from other threads.
|
||||
|
||||
protected: // protected for jvmtiRawMonitor
|
||||
void * volatile _owner; // pointer to owning thread OR BasicLock
|
||||
volatile intptr_t _recursions; // recursion count, 0 for first entry
|
||||
private:
|
||||
int OwnerIsThread ; // _owner is (Thread *) vs SP/BasicLock
|
||||
ObjectWaiter * volatile _cxq ; // LL of recently-arrived threads blocked on entry.
|
||||
// The list is actually composed of WaitNodes, acting
|
||||
// as proxies for Threads.
|
||||
protected:
|
||||
ObjectWaiter * volatile _EntryList ; // Threads blocked on entry or reentry.
|
||||
private:
|
||||
Thread * volatile _succ ; // Heir presumptive thread - used for futile wakeup throttling
|
||||
Thread * volatile _Responsible ;
|
||||
int _PromptDrain ; // rqst to drain cxq into EntryList ASAP
|
||||
|
@ -196,8 +259,12 @@ class ObjectMonitor {
|
|||
volatile intptr_t _count; // reference count to prevent reclaimation/deflation
|
||||
// at stop-the-world time. See deflate_idle_monitors().
|
||||
// _count is approximately |_WaitSet| + |_EntryList|
|
||||
protected:
|
||||
volatile intptr_t _waiters; // number of waiting threads
|
||||
private:
|
||||
protected:
|
||||
ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor
|
||||
private:
|
||||
volatile int _WaitSetLock; // protects Wait Queue - simple spinlock
|
||||
|
||||
public:
|
||||
|
@ -205,4 +272,37 @@ class ObjectMonitor {
|
|||
ObjectMonitor * FreeNext ; // Free list linkage
|
||||
intptr_t StatA, StatsB ;
|
||||
|
||||
public:
|
||||
static void Initialize () ;
|
||||
static PerfCounter * _sync_ContendedLockAttempts ;
|
||||
static PerfCounter * _sync_FutileWakeups ;
|
||||
static PerfCounter * _sync_Parks ;
|
||||
static PerfCounter * _sync_EmptyNotifications ;
|
||||
static PerfCounter * _sync_Notifications ;
|
||||
static PerfCounter * _sync_SlowEnter ;
|
||||
static PerfCounter * _sync_SlowExit ;
|
||||
static PerfCounter * _sync_SlowNotify ;
|
||||
static PerfCounter * _sync_SlowNotifyAll ;
|
||||
static PerfCounter * _sync_FailedSpins ;
|
||||
static PerfCounter * _sync_SuccessfulSpins ;
|
||||
static PerfCounter * _sync_PrivateA ;
|
||||
static PerfCounter * _sync_PrivateB ;
|
||||
static PerfCounter * _sync_MonInCirculation ;
|
||||
static PerfCounter * _sync_MonScavenged ;
|
||||
static PerfCounter * _sync_Inflations ;
|
||||
static PerfCounter * _sync_Deflations ;
|
||||
static PerfLongVariable * _sync_MonExtant ;
|
||||
|
||||
public:
|
||||
static int Knob_Verbose;
|
||||
static int Knob_SpinLimit;
|
||||
};
|
||||
|
||||
#undef TEVENT
|
||||
#define TEVENT(nom) {if (SyncVerbose) FEVENT(nom); }
|
||||
|
||||
#define FEVENT(nom) { static volatile int ctr = 0 ; int v = ++ctr ; if ((v & (v-1)) == 0) { ::printf (#nom " : %d \n", v); ::fflush(stdout); }}
|
||||
|
||||
#undef TEVENT
|
||||
#define TEVENT(nom) {;}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue