diff -r 75ab0162aa84 -r fa83ab460c54 src/share/vm/runtime/objectMonitor.hpp --- a/src/share/vm/runtime/objectMonitor.hpp Mon Oct 18 09:33:24 2010 -0700 +++ b/src/share/vm/runtime/objectMonitor.hpp Fri Oct 22 15:59:34 2010 -0400 @@ -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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ 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) {;} +