--- a/hotspot/src/share/vm/runtime/objectMonitor.hpp Mon Oct 18 09:33:24 2010 -0700
+++ b/hotspot/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; }
+
+ // 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 ;
+ }
- intptr_t recursions() const { return _recursions; }
+ ~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) {;}
+