duke@435: /* sla@5237: * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_RUNTIME_OBJECTMONITOR_HPP stefank@2314: #define SHARE_VM_RUNTIME_OBJECTMONITOR_HPP stefank@2314: stefank@2314: #include "runtime/os.hpp" stefank@2325: #include "runtime/park.hpp" stefank@2314: #include "runtime/perfData.hpp" stefank@2314: acorn@2233: // ObjectWaiter serves as a "proxy" or surrogate thread. acorn@2233: // TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific acorn@2233: // ParkEvent instead. Beware, however, that the JVMTI code acorn@2233: // knows about ObjectWaiters, so we'll have to reconcile that code. acorn@2233: // See next_waiter(), first_waiter(), etc. acorn@2233: acorn@2233: class ObjectWaiter : public StackObj { acorn@2233: public: acorn@2233: enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ; acorn@2233: enum Sorted { PREPEND, APPEND, SORTED } ; acorn@2233: ObjectWaiter * volatile _next; acorn@2233: ObjectWaiter * volatile _prev; acorn@2233: Thread* _thread; sla@5237: jlong _notifier_tid; acorn@2233: ParkEvent * _event; acorn@2233: volatile int _notified ; acorn@2233: volatile TStates TState ; acorn@2233: Sorted _Sorted ; // List placement disposition acorn@2233: bool _active ; // Contention monitoring is enabled acorn@2233: public: acorn@2233: ObjectWaiter(Thread* thread); acorn@2233: acorn@2233: void wait_reenter_begin(ObjectMonitor *mon); acorn@2233: void wait_reenter_end(ObjectMonitor *mon); acorn@2233: }; acorn@2233: sla@5237: // forward declaration to avoid include tracing.hpp sla@5237: class EventJavaMonitorWait; sla@5237: duke@435: // WARNING: duke@435: // This is a very sensitive and fragile class. DO NOT make any duke@435: // change unless you are fully aware of the underlying semantics. duke@435: duke@435: // This class can not inherit from any other class, because I have duke@435: // to let the displaced header be the very first word. Otherwise I duke@435: // have to let markOop include this file, which would export the duke@435: // monitor data structure to everywhere. duke@435: // duke@435: // The ObjectMonitor class is used to implement JavaMonitors which have duke@435: // transformed from the lightweight structure of the thread stack to a duke@435: // heavy weight lock due to contention duke@435: duke@435: // It is also used as RawMonitor by the JVMTI duke@435: duke@435: duke@435: class ObjectMonitor { duke@435: public: duke@435: enum { duke@435: OM_OK, // no error duke@435: OM_SYSTEM_ERROR, // operating system error duke@435: OM_ILLEGAL_MONITOR_STATE, // IllegalMonitorStateException duke@435: OM_INTERRUPTED, // Thread.interrupt() duke@435: OM_TIMED_OUT // Object.wait() timed out duke@435: }; duke@435: duke@435: public: duke@435: // TODO-FIXME: the "offset" routines should return a type of off_t instead of int ... duke@435: // ByteSize would also be an appropriate type. duke@435: static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); } duke@435: static int object_offset_in_bytes() { return offset_of(ObjectMonitor, _object); } duke@435: static int owner_offset_in_bytes() { return offset_of(ObjectMonitor, _owner); } duke@435: static int count_offset_in_bytes() { return offset_of(ObjectMonitor, _count); } duke@435: static int recursions_offset_in_bytes() { return offset_of(ObjectMonitor, _recursions); } duke@435: static int cxq_offset_in_bytes() { return offset_of(ObjectMonitor, _cxq) ; } duke@435: static int succ_offset_in_bytes() { return offset_of(ObjectMonitor, _succ) ; } duke@435: static int EntryList_offset_in_bytes() { return offset_of(ObjectMonitor, _EntryList); } duke@435: static int FreeNext_offset_in_bytes() { return offset_of(ObjectMonitor, FreeNext); } duke@435: static int WaitSet_offset_in_bytes() { return offset_of(ObjectMonitor, _WaitSet) ; } duke@435: static int Responsible_offset_in_bytes() { return offset_of(ObjectMonitor, _Responsible);} duke@435: static int Spinner_offset_in_bytes() { return offset_of(ObjectMonitor, _Spinner); } duke@435: duke@435: public: duke@435: // Eventaully we'll make provisions for multiple callbacks, but duke@435: // now one will suffice. duke@435: static int (*SpinCallbackFunction)(intptr_t, int) ; duke@435: static intptr_t SpinCallbackArgument ; duke@435: duke@435: duke@435: public: duke@435: markOop header() const; duke@435: void set_header(markOop hdr); duke@435: acorn@2233: intptr_t is_busy() const { acorn@2233: // TODO-FIXME: merge _count and _waiters. acorn@2233: // TODO-FIXME: assert _owner == null implies _recursions = 0 acorn@2233: // TODO-FIXME: assert _WaitSet != null implies _count > 0 acorn@2233: return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ; acorn@2233: } acorn@2233: duke@435: intptr_t is_entered(Thread* current) const; duke@435: duke@435: void* owner() const; duke@435: void set_owner(void* owner); duke@435: duke@435: intptr_t waiters() const; duke@435: duke@435: intptr_t count() const; duke@435: void set_count(intptr_t count); duke@435: intptr_t contentions() const ; acorn@2233: intptr_t recursions() const { return _recursions; } duke@435: duke@435: // JVM/DI GetMonitorInfo() needs this acorn@2233: ObjectWaiter* first_waiter() { return _WaitSet; } acorn@2233: ObjectWaiter* next_waiter(ObjectWaiter* o) { return o->_next; } acorn@2233: Thread* thread_of_waiter(ObjectWaiter* o) { return o->_thread; } duke@435: acorn@2233: // initialize the monitor, exception the semaphore, all other fields acorn@2233: // are simple integers or pointers acorn@2233: ObjectMonitor() { acorn@2233: _header = NULL; acorn@2233: _count = 0; acorn@2233: _waiters = 0, acorn@2233: _recursions = 0; acorn@2233: _object = NULL; acorn@2233: _owner = NULL; acorn@2233: _WaitSet = NULL; acorn@2233: _WaitSetLock = 0 ; acorn@2233: _Responsible = NULL ; acorn@2233: _succ = NULL ; acorn@2233: _cxq = NULL ; acorn@2233: FreeNext = NULL ; acorn@2233: _EntryList = NULL ; acorn@2233: _SpinFreq = 0 ; acorn@2233: _SpinClock = 0 ; acorn@2233: OwnerIsThread = 0 ; sla@5237: _previous_owner_tid = 0; acorn@2233: } acorn@2233: acorn@2233: ~ObjectMonitor() { acorn@2233: // TODO: Add asserts ... acorn@2233: // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 acorn@2233: // _count == 0 _EntryList == NULL etc acorn@2233: } acorn@2233: acorn@2233: private: acorn@2233: void Recycle () { acorn@2233: // TODO: add stronger asserts ... acorn@2233: // _cxq == 0 _succ == NULL _owner == NULL _waiters == 0 acorn@2233: // _count == 0 EntryList == NULL acorn@2233: // _recursions == 0 _WaitSet == NULL acorn@2233: // TODO: assert (is_busy()|_recursions) == 0 acorn@2233: _succ = NULL ; acorn@2233: _EntryList = NULL ; acorn@2233: _cxq = NULL ; acorn@2233: _WaitSet = NULL ; acorn@2233: _recursions = 0 ; acorn@2233: _SpinFreq = 0 ; acorn@2233: _SpinClock = 0 ; acorn@2233: OwnerIsThread = 0 ; acorn@2233: } acorn@2233: acorn@2233: public: duke@435: duke@435: void* object() const; duke@435: void* object_addr(); duke@435: void set_object(void* obj); duke@435: duke@435: bool check(TRAPS); // true if the thread owns the monitor. duke@435: void check_slow(TRAPS); duke@435: void clear(); duke@435: #ifndef PRODUCT duke@435: void verify(); duke@435: void print(); duke@435: #endif duke@435: duke@435: bool try_enter (TRAPS) ; duke@435: void enter(TRAPS); sla@5237: void exit(bool not_suspended, TRAPS); duke@435: void wait(jlong millis, bool interruptable, TRAPS); duke@435: void notify(TRAPS); duke@435: void notifyAll(TRAPS); duke@435: duke@435: // Use the following at your own risk duke@435: intptr_t complete_exit(TRAPS); duke@435: void reenter(intptr_t recursions, TRAPS); duke@435: duke@435: private: duke@435: void AddWaiter (ObjectWaiter * waiter) ; acorn@2233: static void DeferredInitialize(); duke@435: duke@435: ObjectWaiter * DequeueWaiter () ; duke@435: void DequeueSpecificWaiter (ObjectWaiter * waiter) ; duke@435: void EnterI (TRAPS) ; duke@435: void ReenterI (Thread * Self, ObjectWaiter * SelfNode) ; duke@435: void UnlinkAfterAcquire (Thread * Self, ObjectWaiter * SelfNode) ; duke@435: int TryLock (Thread * Self) ; duke@435: int NotRunnable (Thread * Self, Thread * Owner) ; duke@435: int TrySpin_Fixed (Thread * Self) ; duke@435: int TrySpin_VaryFrequency (Thread * Self) ; duke@435: int TrySpin_VaryDuration (Thread * Self) ; duke@435: void ctAsserts () ; duke@435: void ExitEpilog (Thread * Self, ObjectWaiter * Wakee) ; duke@435: bool ExitSuspendEquivalent (JavaThread * Self) ; sla@5237: void post_monitor_wait_event(EventJavaMonitorWait * event, sla@5237: jlong notifier_tid, sla@5237: jlong timeout, sla@5237: bool timedout); duke@435: duke@435: private: duke@435: friend class ObjectSynchronizer; duke@435: friend class ObjectWaiter; duke@435: friend class VMStructs; duke@435: duke@435: // WARNING: this must be the very first word of ObjectMonitor duke@435: // This means this class can't use any virtual member functions. duke@435: // TODO-FIXME: assert that offsetof(_header) is 0 or get rid of the duke@435: // implicit 0 offset in emitted code. duke@435: duke@435: volatile markOop _header; // displaced object header word - mark duke@435: void* volatile _object; // backward object pointer - strong root duke@435: duke@435: double SharingPad [1] ; // temp to reduce false sharing duke@435: duke@435: // All the following fields must be machine word aligned duke@435: // The VM assumes write ordering wrt these fields, which can be duke@435: // read from other threads. duke@435: acorn@2233: protected: // protected for jvmtiRawMonitor duke@435: void * volatile _owner; // pointer to owning thread OR BasicLock sla@5237: volatile jlong _previous_owner_tid; // thread id of the previous owner of the monitor duke@435: volatile intptr_t _recursions; // recursion count, 0 for first entry acorn@2233: private: duke@435: int OwnerIsThread ; // _owner is (Thread *) vs SP/BasicLock duke@435: ObjectWaiter * volatile _cxq ; // LL of recently-arrived threads blocked on entry. duke@435: // The list is actually composed of WaitNodes, acting duke@435: // as proxies for Threads. acorn@2233: protected: duke@435: ObjectWaiter * volatile _EntryList ; // Threads blocked on entry or reentry. acorn@2233: private: duke@435: Thread * volatile _succ ; // Heir presumptive thread - used for futile wakeup throttling duke@435: Thread * volatile _Responsible ; duke@435: int _PromptDrain ; // rqst to drain cxq into EntryList ASAP duke@435: duke@435: volatile int _Spinner ; // for exit->spinner handoff optimization duke@435: volatile int _SpinFreq ; // Spin 1-out-of-N attempts: success rate duke@435: volatile int _SpinClock ; duke@435: volatile int _SpinDuration ; duke@435: volatile intptr_t _SpinState ; // MCS/CLH list of spinners duke@435: duke@435: // TODO-FIXME: _count, _waiters and _recursions should be of duke@435: // type int, or int32_t but not intptr_t. There's no reason duke@435: // to use 64-bit fields for these variables on a 64-bit JVM. duke@435: duke@435: volatile intptr_t _count; // reference count to prevent reclaimation/deflation duke@435: // at stop-the-world time. See deflate_idle_monitors(). duke@435: // _count is approximately |_WaitSet| + |_EntryList| acorn@2233: protected: duke@435: volatile intptr_t _waiters; // number of waiting threads acorn@2233: private: acorn@2233: protected: duke@435: ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor acorn@2233: private: duke@435: volatile int _WaitSetLock; // protects Wait Queue - simple spinlock duke@435: duke@435: public: duke@435: int _QMix ; // Mixed prepend queue discipline duke@435: ObjectMonitor * FreeNext ; // Free list linkage duke@435: intptr_t StatA, StatsB ; duke@435: acorn@2233: public: acorn@2233: static void Initialize () ; acorn@2233: static PerfCounter * _sync_ContendedLockAttempts ; acorn@2233: static PerfCounter * _sync_FutileWakeups ; acorn@2233: static PerfCounter * _sync_Parks ; acorn@2233: static PerfCounter * _sync_EmptyNotifications ; acorn@2233: static PerfCounter * _sync_Notifications ; acorn@2233: static PerfCounter * _sync_SlowEnter ; acorn@2233: static PerfCounter * _sync_SlowExit ; acorn@2233: static PerfCounter * _sync_SlowNotify ; acorn@2233: static PerfCounter * _sync_SlowNotifyAll ; acorn@2233: static PerfCounter * _sync_FailedSpins ; acorn@2233: static PerfCounter * _sync_SuccessfulSpins ; acorn@2233: static PerfCounter * _sync_PrivateA ; acorn@2233: static PerfCounter * _sync_PrivateB ; acorn@2233: static PerfCounter * _sync_MonInCirculation ; acorn@2233: static PerfCounter * _sync_MonScavenged ; acorn@2233: static PerfCounter * _sync_Inflations ; acorn@2233: static PerfCounter * _sync_Deflations ; acorn@2233: static PerfLongVariable * _sync_MonExtant ; acorn@2233: acorn@2233: public: acorn@2233: static int Knob_Verbose; acorn@2233: static int Knob_SpinLimit; coleenp@5614: void* operator new (size_t size) throw() { minqi@5103: return AllocateHeap(size, mtInternal); minqi@5103: } coleenp@5614: void* operator new[] (size_t size) throw() { minqi@5103: return operator new (size); minqi@5103: } minqi@5103: void operator delete(void* p) { minqi@5103: FreeHeap(p, mtInternal); minqi@5103: } minqi@5103: void operator delete[] (void *p) { minqi@5103: operator delete(p); minqi@5103: } duke@435: }; acorn@2233: acorn@2233: #undef TEVENT acorn@2233: #define TEVENT(nom) {if (SyncVerbose) FEVENT(nom); } acorn@2233: acorn@2233: #define FEVENT(nom) { static volatile int ctr = 0 ; int v = ++ctr ; if ((v & (v-1)) == 0) { ::printf (#nom " : %d \n", v); ::fflush(stdout); }} acorn@2233: acorn@2233: #undef TEVENT acorn@2233: #define TEVENT(nom) {;} acorn@2233: stefank@2314: stefank@2314: #endif // SHARE_VM_RUNTIME_OBJECTMONITOR_HPP