duke@435: /* trims@1907: * Copyright (c) 1998, 2007, 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: 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 ObjectWaiter; 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: ObjectMonitor(); duke@435: ~ObjectMonitor(); duke@435: duke@435: markOop header() const; duke@435: void set_header(markOop hdr); duke@435: duke@435: intptr_t is_busy() const; 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 ; duke@435: duke@435: // JVM/DI GetMonitorInfo() needs this duke@435: Thread * thread_of_waiter (ObjectWaiter *) ; duke@435: ObjectWaiter * first_waiter () ; duke@435: ObjectWaiter * next_waiter(ObjectWaiter* o); duke@435: duke@435: intptr_t recursions() const { return _recursions; } 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); duke@435: void exit(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: int raw_enter(TRAPS); duke@435: int raw_exit(TRAPS); duke@435: int raw_wait(jlong millis, bool interruptable, TRAPS); duke@435: int raw_notify(TRAPS); duke@435: int raw_notifyAll(TRAPS); duke@435: duke@435: private: duke@435: // JVMTI support -- remove ASAP duke@435: int SimpleEnter (Thread * Self) ; duke@435: int SimpleExit (Thread * Self) ; duke@435: int SimpleWait (Thread * Self, jlong millis) ; duke@435: int SimpleNotify (Thread * Self, bool All) ; duke@435: duke@435: private: duke@435: void Recycle () ; duke@435: void AddWaiter (ObjectWaiter * waiter) ; 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) ; 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: duke@435: void * volatile _owner; // pointer to owning thread OR BasicLock duke@435: volatile intptr_t _recursions; // recursion count, 0 for first entry 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. duke@435: ObjectWaiter * volatile _EntryList ; // Threads blocked on entry or reentry. 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| duke@435: volatile intptr_t _waiters; // number of waiting threads duke@435: ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor 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: duke@435: };