src/share/vm/runtime/objectMonitor.hpp

changeset 2233
fa83ab460c54
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
     1.1 --- a/src/share/vm/runtime/objectMonitor.hpp	Mon Oct 18 09:33:24 2010 -0700
     1.2 +++ b/src/share/vm/runtime/objectMonitor.hpp	Fri Oct 22 15:59:34 2010 -0400
     1.3 @@ -22,6 +22,32 @@
     1.4   *
     1.5   */
     1.6  
     1.7 +
     1.8 +// ObjectWaiter serves as a "proxy" or surrogate thread.
     1.9 +// TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific
    1.10 +// ParkEvent instead.  Beware, however, that the JVMTI code
    1.11 +// knows about ObjectWaiters, so we'll have to reconcile that code.
    1.12 +// See next_waiter(), first_waiter(), etc.
    1.13 +
    1.14 +class ObjectWaiter : public StackObj {
    1.15 + public:
    1.16 +  enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
    1.17 +  enum Sorted  { PREPEND, APPEND, SORTED } ;
    1.18 +  ObjectWaiter * volatile _next;
    1.19 +  ObjectWaiter * volatile _prev;
    1.20 +  Thread*       _thread;
    1.21 +  ParkEvent *   _event;
    1.22 +  volatile int  _notified ;
    1.23 +  volatile TStates TState ;
    1.24 +  Sorted        _Sorted ;           // List placement disposition
    1.25 +  bool          _active ;           // Contention monitoring is enabled
    1.26 + public:
    1.27 +  ObjectWaiter(Thread* thread);
    1.28 +
    1.29 +  void wait_reenter_begin(ObjectMonitor *mon);
    1.30 +  void wait_reenter_end(ObjectMonitor *mon);
    1.31 +};
    1.32 +
    1.33  // WARNING:
    1.34  //   This is a very sensitive and fragile class. DO NOT make any
    1.35  // change unless you are fully aware of the underlying semantics.
    1.36 @@ -38,8 +64,6 @@
    1.37  // It is also used as RawMonitor by the JVMTI
    1.38  
    1.39  
    1.40 -class ObjectWaiter;
    1.41 -
    1.42  class ObjectMonitor {
    1.43   public:
    1.44    enum {
    1.45 @@ -74,13 +98,16 @@
    1.46  
    1.47  
    1.48   public:
    1.49 -  ObjectMonitor();
    1.50 -  ~ObjectMonitor();
    1.51 -
    1.52    markOop   header() const;
    1.53    void      set_header(markOop hdr);
    1.54  
    1.55 -  intptr_t  is_busy() const;
    1.56 +  intptr_t is_busy() const {
    1.57 +    // TODO-FIXME: merge _count and _waiters.
    1.58 +    // TODO-FIXME: assert _owner == null implies _recursions = 0
    1.59 +    // TODO-FIXME: assert _WaitSet != null implies _count > 0
    1.60 +    return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ;
    1.61 +  }
    1.62 +
    1.63    intptr_t  is_entered(Thread* current) const;
    1.64  
    1.65    void*     owner() const;
    1.66 @@ -91,13 +118,58 @@
    1.67    intptr_t  count() const;
    1.68    void      set_count(intptr_t count);
    1.69    intptr_t  contentions() const ;
    1.70 +  intptr_t  recursions() const                                         { return _recursions; }
    1.71  
    1.72    // JVM/DI GetMonitorInfo() needs this
    1.73 -  Thread *  thread_of_waiter (ObjectWaiter *) ;
    1.74 -  ObjectWaiter * first_waiter () ;
    1.75 -  ObjectWaiter * next_waiter(ObjectWaiter* o);
    1.76 +  ObjectWaiter* first_waiter()                                         { return _WaitSet; }
    1.77 +  ObjectWaiter* next_waiter(ObjectWaiter* o)                           { return o->_next; }
    1.78 +  Thread* thread_of_waiter(ObjectWaiter* o)                            { return o->_thread; }
    1.79  
    1.80 -  intptr_t  recursions() const { return _recursions; }
    1.81 +  // initialize the monitor, exception the semaphore, all other fields
    1.82 +  // are simple integers or pointers
    1.83 +  ObjectMonitor() {
    1.84 +    _header       = NULL;
    1.85 +    _count        = 0;
    1.86 +    _waiters      = 0,
    1.87 +    _recursions   = 0;
    1.88 +    _object       = NULL;
    1.89 +    _owner        = NULL;
    1.90 +    _WaitSet      = NULL;
    1.91 +    _WaitSetLock  = 0 ;
    1.92 +    _Responsible  = NULL ;
    1.93 +    _succ         = NULL ;
    1.94 +    _cxq          = NULL ;
    1.95 +    FreeNext      = NULL ;
    1.96 +    _EntryList    = NULL ;
    1.97 +    _SpinFreq     = 0 ;
    1.98 +    _SpinClock    = 0 ;
    1.99 +    OwnerIsThread = 0 ;
   1.100 +  }
   1.101 +
   1.102 +  ~ObjectMonitor() {
   1.103 +   // TODO: Add asserts ...
   1.104 +   // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
   1.105 +   // _count == 0 _EntryList  == NULL etc
   1.106 +  }
   1.107 +
   1.108 +private:
   1.109 +  void Recycle () {
   1.110 +    // TODO: add stronger asserts ...
   1.111 +    // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
   1.112 +    // _count == 0 EntryList  == NULL
   1.113 +    // _recursions == 0 _WaitSet == NULL
   1.114 +    // TODO: assert (is_busy()|_recursions) == 0
   1.115 +    _succ          = NULL ;
   1.116 +    _EntryList     = NULL ;
   1.117 +    _cxq           = NULL ;
   1.118 +    _WaitSet       = NULL ;
   1.119 +    _recursions    = 0 ;
   1.120 +    _SpinFreq      = 0 ;
   1.121 +    _SpinClock     = 0 ;
   1.122 +    OwnerIsThread  = 0 ;
   1.123 +  }
   1.124 +
   1.125 +public:
   1.126  
   1.127    void*     object() const;
   1.128    void*     object_addr();
   1.129 @@ -122,22 +194,9 @@
   1.130    intptr_t  complete_exit(TRAPS);
   1.131    void      reenter(intptr_t recursions, TRAPS);
   1.132  
   1.133 -  int       raw_enter(TRAPS);
   1.134 -  int       raw_exit(TRAPS);
   1.135 -  int       raw_wait(jlong millis, bool interruptable, TRAPS);
   1.136 -  int       raw_notify(TRAPS);
   1.137 -  int       raw_notifyAll(TRAPS);
   1.138 -
   1.139   private:
   1.140 -  // JVMTI support -- remove ASAP
   1.141 -  int       SimpleEnter (Thread * Self) ;
   1.142 -  int       SimpleExit  (Thread * Self) ;
   1.143 -  int       SimpleWait  (Thread * Self, jlong millis) ;
   1.144 -  int       SimpleNotify (Thread * Self, bool All) ;
   1.145 -
   1.146 - private:
   1.147 -  void      Recycle () ;
   1.148    void      AddWaiter (ObjectWaiter * waiter) ;
   1.149 +  static    void DeferredInitialize();
   1.150  
   1.151    ObjectWaiter * DequeueWaiter () ;
   1.152    void      DequeueSpecificWaiter (ObjectWaiter * waiter) ;
   1.153 @@ -172,13 +231,17 @@
   1.154    // The VM assumes write ordering wrt these fields, which can be
   1.155    // read from other threads.
   1.156  
   1.157 + protected:                         // protected for jvmtiRawMonitor
   1.158    void *  volatile _owner;          // pointer to owning thread OR BasicLock
   1.159    volatile intptr_t  _recursions;   // recursion count, 0 for first entry
   1.160 + private:
   1.161    int OwnerIsThread ;               // _owner is (Thread *) vs SP/BasicLock
   1.162    ObjectWaiter * volatile _cxq ;    // LL of recently-arrived threads blocked on entry.
   1.163                                      // The list is actually composed of WaitNodes, acting
   1.164                                      // as proxies for Threads.
   1.165 + protected:
   1.166    ObjectWaiter * volatile _EntryList ;     // Threads blocked on entry or reentry.
   1.167 + private:
   1.168    Thread * volatile _succ ;          // Heir presumptive thread - used for futile wakeup throttling
   1.169    Thread * volatile _Responsible ;
   1.170    int _PromptDrain ;                // rqst to drain cxq into EntryList ASAP
   1.171 @@ -196,8 +259,12 @@
   1.172    volatile intptr_t  _count;        // reference count to prevent reclaimation/deflation
   1.173                                      // at stop-the-world time.  See deflate_idle_monitors().
   1.174                                      // _count is approximately |_WaitSet| + |_EntryList|
   1.175 + protected:
   1.176    volatile intptr_t  _waiters;      // number of waiting threads
   1.177 + private:
   1.178 + protected:
   1.179    ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor
   1.180 + private:
   1.181    volatile int _WaitSetLock;        // protects Wait Queue - simple spinlock
   1.182  
   1.183   public:
   1.184 @@ -205,4 +272,37 @@
   1.185    ObjectMonitor * FreeNext ;        // Free list linkage
   1.186    intptr_t StatA, StatsB ;
   1.187  
   1.188 + public:
   1.189 +  static void Initialize () ;
   1.190 +  static PerfCounter * _sync_ContendedLockAttempts ;
   1.191 +  static PerfCounter * _sync_FutileWakeups ;
   1.192 +  static PerfCounter * _sync_Parks ;
   1.193 +  static PerfCounter * _sync_EmptyNotifications ;
   1.194 +  static PerfCounter * _sync_Notifications ;
   1.195 +  static PerfCounter * _sync_SlowEnter ;
   1.196 +  static PerfCounter * _sync_SlowExit ;
   1.197 +  static PerfCounter * _sync_SlowNotify ;
   1.198 +  static PerfCounter * _sync_SlowNotifyAll ;
   1.199 +  static PerfCounter * _sync_FailedSpins ;
   1.200 +  static PerfCounter * _sync_SuccessfulSpins ;
   1.201 +  static PerfCounter * _sync_PrivateA ;
   1.202 +  static PerfCounter * _sync_PrivateB ;
   1.203 +  static PerfCounter * _sync_MonInCirculation ;
   1.204 +  static PerfCounter * _sync_MonScavenged ;
   1.205 +  static PerfCounter * _sync_Inflations ;
   1.206 +  static PerfCounter * _sync_Deflations ;
   1.207 +  static PerfLongVariable * _sync_MonExtant ;
   1.208 +
   1.209 + public:
   1.210 +  static int Knob_Verbose;
   1.211 +  static int Knob_SpinLimit;
   1.212  };
   1.213 +
   1.214 +#undef TEVENT
   1.215 +#define TEVENT(nom) {if (SyncVerbose) FEVENT(nom); }
   1.216 +
   1.217 +#define FEVENT(nom) { static volatile int ctr = 0 ; int v = ++ctr ; if ((v & (v-1)) == 0) { ::printf (#nom " : %d \n", v); ::fflush(stdout); }}
   1.218 +
   1.219 +#undef  TEVENT
   1.220 +#define TEVENT(nom) {;}
   1.221 +

mercurial