aoqi@0: /* aoqi@0: * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_RUNTIME_MUTEX_HPP aoqi@0: #define SHARE_VM_RUNTIME_MUTEX_HPP aoqi@0: aoqi@0: #include "memory/allocation.hpp" aoqi@0: #include "runtime/os.hpp" aoqi@0: #include "utilities/histogram.hpp" aoqi@0: aoqi@0: // The SplitWord construct allows us to colocate the contention queue aoqi@0: // (cxq) with the lock-byte. The queue elements are ParkEvents, which are aoqi@0: // always aligned on 256-byte addresses - the least significant byte of aoqi@0: // a ParkEvent is always 0. Colocating the lock-byte with the queue aoqi@0: // allows us to easily avoid what would otherwise be a race in lock() aoqi@0: // if we were to use two completely separate fields for the contention queue aoqi@0: // and the lock indicator. Specifically, colocation renders us immune aoqi@0: // from the race where a thread might enqueue itself in the lock() slow-path aoqi@0: // immediately after the lock holder drops the outer lock in the unlock() aoqi@0: // fast-path. aoqi@0: // aoqi@0: // Colocation allows us to use a fast-path unlock() form that uses aoqi@0: // A MEMBAR instead of a CAS. MEMBAR has lower local latency than CAS aoqi@0: // on many platforms. aoqi@0: // aoqi@0: // See: aoqi@0: // + http://blogs.sun.com/dave/entry/biased_locking_in_hotspot aoqi@0: // + http://blogs.sun.com/dave/resource/synchronization-public2.pdf aoqi@0: // aoqi@0: // Note that we're *not* using word-tearing the classic sense. aoqi@0: // The lock() fast-path will CAS the lockword and the unlock() aoqi@0: // fast-path will store into the lock-byte colocated within the lockword. aoqi@0: // We depend on the fact that all our reference platforms have aoqi@0: // coherent and atomic byte accesses. More precisely, byte stores aoqi@0: // interoperate in a safe, sane, and expected manner with respect to aoqi@0: // CAS, ST and LDs to the full-word containing the byte. aoqi@0: // If you're porting HotSpot to a platform where that isn't the case aoqi@0: // then you'll want change the unlock() fast path from: aoqi@0: // STB;MEMBAR #storeload; LDN aoqi@0: // to a full-word CAS of the lockword. aoqi@0: aoqi@0: aoqi@0: union SplitWord { // full-word with separately addressable LSB aoqi@0: volatile intptr_t FullWord ; aoqi@0: volatile void * Address ; aoqi@0: volatile jbyte Bytes [sizeof(intptr_t)] ; aoqi@0: } ; aoqi@0: aoqi@0: // Endian-ness ... index of least-significant byte in SplitWord.Bytes[] aoqi@0: #ifdef VM_LITTLE_ENDIAN aoqi@0: #define _LSBINDEX 0 aoqi@0: #else aoqi@0: #define _LSBINDEX (sizeof(intptr_t)-1) aoqi@0: #endif aoqi@0: aoqi@0: class ParkEvent ; aoqi@0: aoqi@0: // See orderAccess.hpp. We assume throughout the VM that mutex lock and aoqi@0: // try_lock do fence-lock-acquire, and that unlock does a release-unlock, aoqi@0: // *in that order*. If their implementations change such that these aoqi@0: // assumptions are violated, a whole lot of code will break. aoqi@0: aoqi@0: // The default length of monitor name is chosen to be 64 to avoid false sharing. aoqi@0: static const int MONITOR_NAME_LEN = 64; aoqi@0: aoqi@0: class Monitor : public CHeapObj { aoqi@0: aoqi@0: public: aoqi@0: // A special lock: Is a lock where you are guaranteed not to block while you are aoqi@0: // holding it, i.e., no vm operation can happen, taking other locks, etc. aoqi@0: // NOTE: It is critical that the rank 'special' be the lowest (earliest) aoqi@0: // (except for "event"?) for the deadlock dection to work correctly. aoqi@0: // The rank native is only for use in Mutex's created by JVM_RawMonitorCreate, aoqi@0: // which being external to the VM are not subject to deadlock detection. aoqi@0: // The rank safepoint is used only for synchronization in reaching a aoqi@0: // safepoint and leaving a safepoint. It is only used for the Safepoint_lock aoqi@0: // currently. While at a safepoint no mutexes of rank safepoint are held aoqi@0: // by any thread. aoqi@0: // The rank named "leaf" is probably historical (and should aoqi@0: // be changed) -- mutexes of this rank aren't really leaf mutexes aoqi@0: // at all. aoqi@0: enum lock_types { aoqi@0: event, aoqi@0: special, aoqi@0: suspend_resume, aoqi@0: leaf = suspend_resume + 2, aoqi@0: safepoint = leaf + 10, aoqi@0: barrier = safepoint + 1, aoqi@0: nonleaf = barrier + 1, aoqi@0: max_nonleaf = nonleaf + 900, aoqi@0: native = max_nonleaf + 1 aoqi@0: }; aoqi@0: aoqi@0: // The WaitSet and EntryList linked lists are composed of ParkEvents. aoqi@0: // I use ParkEvent instead of threads as ParkEvents are immortal and aoqi@0: // type-stable, meaning we can safely unpark() a possibly stale aoqi@0: // list element in the unlock()-path. aoqi@0: aoqi@0: protected: // Monitor-Mutex metadata aoqi@0: SplitWord _LockWord ; // Contention queue (cxq) colocated with Lock-byte aoqi@0: enum LockWordBits { _LBIT=1 } ; aoqi@0: Thread * volatile _owner; // The owner of the lock aoqi@0: // Consider sequestering _owner on its own $line aoqi@0: // to aid future synchronization mechanisms. aoqi@0: ParkEvent * volatile _EntryList ; // List of threads waiting for entry aoqi@0: ParkEvent * volatile _OnDeck ; // heir-presumptive aoqi@0: volatile intptr_t _WaitLock [1] ; // Protects _WaitSet aoqi@0: ParkEvent * volatile _WaitSet ; // LL of ParkEvents aoqi@0: volatile bool _snuck; // Used for sneaky locking (evil). aoqi@0: int NotifyCount ; // diagnostic assist aoqi@0: char _name[MONITOR_NAME_LEN]; // Name of mutex aoqi@0: aoqi@0: // Debugging fields for naming, deadlock detection, etc. (some only used in debug mode) aoqi@0: #ifndef PRODUCT aoqi@0: bool _allow_vm_block; aoqi@0: debug_only(int _rank;) // rank (to avoid/detect potential deadlocks) aoqi@0: debug_only(Monitor * _next;) // Used by a Thread to link up owned locks aoqi@0: debug_only(Thread* _last_owner;) // the last thread to own the lock aoqi@0: debug_only(static bool contains(Monitor * locks, Monitor * lock);) aoqi@0: debug_only(static Monitor * get_least_ranked_lock(Monitor * locks);) aoqi@0: debug_only(Monitor * get_least_ranked_lock_besides_this(Monitor * locks);) aoqi@0: #endif aoqi@0: aoqi@0: void set_owner_implementation(Thread* owner) PRODUCT_RETURN; aoqi@0: void check_prelock_state (Thread* thread) PRODUCT_RETURN; aoqi@0: void check_block_state (Thread* thread) PRODUCT_RETURN; aoqi@0: aoqi@0: // platform-dependent support code can go here (in os_.cpp) aoqi@0: public: aoqi@0: enum { aoqi@0: _no_safepoint_check_flag = true, aoqi@0: _allow_vm_block_flag = true, aoqi@0: _as_suspend_equivalent_flag = true aoqi@0: }; aoqi@0: aoqi@0: enum WaitResults { aoqi@0: CONDVAR_EVENT, // Wait returned because of condition variable notification aoqi@0: INTERRUPT_EVENT, // Wait returned because waiting thread was interrupted aoqi@0: NUMBER_WAIT_RESULTS aoqi@0: }; aoqi@0: aoqi@0: private: aoqi@0: int TrySpin (Thread * Self) ; aoqi@0: int TryLock () ; aoqi@0: int TryFast () ; aoqi@0: int AcquireOrPush (ParkEvent * ev) ; aoqi@0: void IUnlock (bool RelaxAssert) ; aoqi@0: void ILock (Thread * Self) ; aoqi@0: int IWait (Thread * Self, jlong timo); aoqi@0: int ILocked () ; aoqi@0: aoqi@0: protected: aoqi@0: static void ClearMonitor (Monitor * m, const char* name = NULL) ; aoqi@0: Monitor() ; aoqi@0: aoqi@0: public: aoqi@0: Monitor(int rank, const char *name, bool allow_vm_block=false); aoqi@0: ~Monitor(); aoqi@0: aoqi@0: // Wait until monitor is notified (or times out). aoqi@0: // Defaults are to make safepoint checks, wait time is forever (i.e., aoqi@0: // zero), and not a suspend-equivalent condition. Returns true if wait aoqi@0: // times out; otherwise returns false. aoqi@0: bool wait(bool no_safepoint_check = !_no_safepoint_check_flag, aoqi@0: long timeout = 0, aoqi@0: bool as_suspend_equivalent = !_as_suspend_equivalent_flag); aoqi@0: bool notify(); aoqi@0: bool notify_all(); aoqi@0: aoqi@0: aoqi@0: void lock(); // prints out warning if VM thread blocks aoqi@0: void lock(Thread *thread); // overloaded with current thread aoqi@0: void unlock(); aoqi@0: bool is_locked() const { return _owner != NULL; } aoqi@0: aoqi@0: bool try_lock(); // Like lock(), but unblocking. It returns false instead aoqi@0: aoqi@0: // Lock without safepoint check. Should ONLY be used by safepoint code and other code aoqi@0: // that is guaranteed not to block while running inside the VM. aoqi@0: void lock_without_safepoint_check(); aoqi@0: void lock_without_safepoint_check (Thread * Self) ; aoqi@0: aoqi@0: // Current owner - not not MT-safe. Can only be used to guarantee that aoqi@0: // the current running thread owns the lock aoqi@0: Thread* owner() const { return _owner; } aoqi@0: bool owned_by_self() const; aoqi@0: aoqi@0: // Support for JVM_RawMonitorEnter & JVM_RawMonitorExit. These can be called by aoqi@0: // non-Java thread. (We should really have a RawMonitor abstraction) aoqi@0: void jvm_raw_lock(); aoqi@0: void jvm_raw_unlock(); aoqi@0: const char *name() const { return _name; } aoqi@0: aoqi@0: void print_on_error(outputStream* st) const; aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: void print_on(outputStream* st) const; aoqi@0: void print() const { print_on(tty); } aoqi@0: debug_only(int rank() const { return _rank; }) aoqi@0: bool allow_vm_block() { return _allow_vm_block; } aoqi@0: aoqi@0: debug_only(Monitor *next() const { return _next; }) aoqi@0: debug_only(void set_next(Monitor *next) { _next = next; }) aoqi@0: #endif aoqi@0: aoqi@0: void set_owner(Thread* owner) { aoqi@0: #ifndef PRODUCT aoqi@0: set_owner_implementation(owner); aoqi@0: debug_only(void verify_Monitor(Thread* thr)); aoqi@0: #else aoqi@0: _owner = owner; aoqi@0: #endif aoqi@0: } aoqi@0: aoqi@0: }; aoqi@0: aoqi@0: // Normally we'd expect Monitor to extend Mutex in the sense that a monitor aoqi@0: // constructed from pthreads primitives might extend a mutex by adding aoqi@0: // a condvar and some extra metadata. In fact this was the case until J2SE7. aoqi@0: // aoqi@0: // Currently, however, the base object is a monitor. Monitor contains all the aoqi@0: // logic for wait(), notify(), etc. Mutex extends monitor and restricts the aoqi@0: // visiblity of wait(), notify(), and notify_all(). aoqi@0: // aoqi@0: // Another viable alternative would have been to have Monitor extend Mutex and aoqi@0: // implement all the normal mutex and wait()-notify() logic in Mutex base class. aoqi@0: // The wait()-notify() facility would be exposed via special protected member functions aoqi@0: // (e.g., _Wait() and _Notify()) in Mutex. Monitor would extend Mutex and expose wait() aoqi@0: // as a call to _Wait(). That is, the public wait() would be a wrapper for the protected aoqi@0: // _Wait(). aoqi@0: // aoqi@0: // An even better alternative is to simply eliminate Mutex:: and use Monitor:: instead. aoqi@0: // After all, monitors are sufficient for Java-level synchronization. At one point in time aoqi@0: // there may have been some benefit to having distinct mutexes and monitors, but that time aoqi@0: // has past. aoqi@0: // aoqi@0: // The Mutex/Monitor design parallels that of Java-monitors, being based on aoqi@0: // thread-specific park-unpark platform-specific primitives. aoqi@0: aoqi@0: aoqi@0: class Mutex : public Monitor { // degenerate Monitor aoqi@0: public: aoqi@0: Mutex (int rank, const char *name, bool allow_vm_block=false); aoqi@0: ~Mutex () ; aoqi@0: private: aoqi@0: bool notify () { ShouldNotReachHere(); return false; } aoqi@0: bool notify_all() { ShouldNotReachHere(); return false; } aoqi@0: bool wait (bool no_safepoint_check, long timeout, bool as_suspend_equivalent) { aoqi@0: ShouldNotReachHere() ; aoqi@0: return false ; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: #endif // SHARE_VM_RUNTIME_MUTEX_HPP