annotate src/share/vm/runtime/mutex.hpp @ 1145:e018e6884bd8

6631166: CMS: better heuristics when combatting fragmentation Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa
author ysr
date Wed, 23 Dec 2009 09:23:54 -0800
parents 354d3184f6b2
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
196
d1605aabd0a1 6719955: Update copyright year
xdono
parents: 55
diff changeset
2 * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 // The SplitWord construct allows us to colocate the contention queue
a61af66fc99e Initial load
duke
parents:
diff changeset
26 // (cxq) with the lock-byte. The queue elements are ParkEvents, which are
a61af66fc99e Initial load
duke
parents:
diff changeset
27 // always aligned on 256-byte addresses - the least significant byte of
a61af66fc99e Initial load
duke
parents:
diff changeset
28 // a ParkEvent is always 0. Colocating the lock-byte with the queue
a61af66fc99e Initial load
duke
parents:
diff changeset
29 // allows us to easily avoid what would otherwise be a race in lock()
a61af66fc99e Initial load
duke
parents:
diff changeset
30 // if we were to use two completely separate fields for the contention queue
a61af66fc99e Initial load
duke
parents:
diff changeset
31 // and the lock indicator. Specifically, colocation renders us immune
a61af66fc99e Initial load
duke
parents:
diff changeset
32 // from the race where a thread might enqueue itself in the lock() slow-path
a61af66fc99e Initial load
duke
parents:
diff changeset
33 // immediately after the lock holder drops the outer lock in the unlock()
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // fast-path.
a61af66fc99e Initial load
duke
parents:
diff changeset
35 //
a61af66fc99e Initial load
duke
parents:
diff changeset
36 // Colocation allows us to use a fast-path unlock() form that uses
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // A MEMBAR instead of a CAS. MEMBAR has lower local latency than CAS
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // on many platforms.
a61af66fc99e Initial load
duke
parents:
diff changeset
39 //
a61af66fc99e Initial load
duke
parents:
diff changeset
40 // See:
a61af66fc99e Initial load
duke
parents:
diff changeset
41 // + http://blogs.sun.com/dave/entry/biased_locking_in_hotspot
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // + http://blogs.sun.com/dave/resource/synchronization-public2.pdf
a61af66fc99e Initial load
duke
parents:
diff changeset
43 //
a61af66fc99e Initial load
duke
parents:
diff changeset
44 // Note that we're *not* using word-tearing the classic sense.
a61af66fc99e Initial load
duke
parents:
diff changeset
45 // The lock() fast-path will CAS the lockword and the unlock()
a61af66fc99e Initial load
duke
parents:
diff changeset
46 // fast-path will store into the lock-byte colocated within the lockword.
a61af66fc99e Initial load
duke
parents:
diff changeset
47 // We depend on the fact that all our reference platforms have
a61af66fc99e Initial load
duke
parents:
diff changeset
48 // coherent and atomic byte accesses. More precisely, byte stores
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // interoperate in a safe, sane, and expected manner with respect to
a61af66fc99e Initial load
duke
parents:
diff changeset
50 // CAS, ST and LDs to the full-word containing the byte.
a61af66fc99e Initial load
duke
parents:
diff changeset
51 // If you're porting HotSpot to a platform where that isn't the case
a61af66fc99e Initial load
duke
parents:
diff changeset
52 // then you'll want change the unlock() fast path from:
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // STB;MEMBAR #storeload; LDN
a61af66fc99e Initial load
duke
parents:
diff changeset
54 // to a full-word CAS of the lockword.
a61af66fc99e Initial load
duke
parents:
diff changeset
55
a61af66fc99e Initial load
duke
parents:
diff changeset
56
a61af66fc99e Initial load
duke
parents:
diff changeset
57 union SplitWord { // full-word with separately addressable LSB
a61af66fc99e Initial load
duke
parents:
diff changeset
58 volatile intptr_t FullWord ;
a61af66fc99e Initial load
duke
parents:
diff changeset
59 volatile void * Address ;
a61af66fc99e Initial load
duke
parents:
diff changeset
60 volatile jbyte Bytes [sizeof(intptr_t)] ;
a61af66fc99e Initial load
duke
parents:
diff changeset
61 } ;
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // Endian-ness ... index of least-significant byte in SplitWord.Bytes[]
1010
354d3184f6b2 6890308: integrate zero assembler hotspot changes
never
parents: 605
diff changeset
64 #ifdef VM_LITTLE_ENDIAN
0
a61af66fc99e Initial load
duke
parents:
diff changeset
65 #define _LSBINDEX 0
a61af66fc99e Initial load
duke
parents:
diff changeset
66 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
67 #define _LSBINDEX (sizeof(intptr_t)-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
68 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
69
a61af66fc99e Initial load
duke
parents:
diff changeset
70 class ParkEvent ;
a61af66fc99e Initial load
duke
parents:
diff changeset
71
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // See orderAccess.hpp. We assume throughout the VM that mutex lock and
a61af66fc99e Initial load
duke
parents:
diff changeset
73 // try_lock do fence-lock-acquire, and that unlock does a release-unlock,
a61af66fc99e Initial load
duke
parents:
diff changeset
74 // *in that order*. If their implementations change such that these
a61af66fc99e Initial load
duke
parents:
diff changeset
75 // assumptions are violated, a whole lot of code will break.
a61af66fc99e Initial load
duke
parents:
diff changeset
76
605
98cb887364d3 6810672: Comment typos
twisti
parents: 196
diff changeset
77 // The default length of monitor name is chosen to be 64 to avoid false sharing.
55
2a8eb116ebbe 6610420: Debug VM crashes during monitor lock rank checking
xlu
parents: 0
diff changeset
78 static const int MONITOR_NAME_LEN = 64;
2a8eb116ebbe 6610420: Debug VM crashes during monitor lock rank checking
xlu
parents: 0
diff changeset
79
0
a61af66fc99e Initial load
duke
parents:
diff changeset
80 class Monitor : public CHeapObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
83 // A special lock: Is a lock where you are guaranteed not to block while you are
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // holding it, i.e., no vm operation can happen, taking other locks, etc.
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // NOTE: It is critical that the rank 'special' be the lowest (earliest)
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // (except for "event"?) for the deadlock dection to work correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // The rank native is only for use in Mutex's created by JVM_RawMonitorCreate,
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // which being external to the VM are not subject to deadlock detection.
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // The rank safepoint is used only for synchronization in reaching a
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // safepoint and leaving a safepoint. It is only used for the Safepoint_lock
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // currently. While at a safepoint no mutexes of rank safepoint are held
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // by any thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // The rank named "leaf" is probably historical (and should
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // be changed) -- mutexes of this rank aren't really leaf mutexes
a61af66fc99e Initial load
duke
parents:
diff changeset
95 // at all.
a61af66fc99e Initial load
duke
parents:
diff changeset
96 enum lock_types {
a61af66fc99e Initial load
duke
parents:
diff changeset
97 event,
a61af66fc99e Initial load
duke
parents:
diff changeset
98 special,
a61af66fc99e Initial load
duke
parents:
diff changeset
99 suspend_resume,
a61af66fc99e Initial load
duke
parents:
diff changeset
100 leaf = suspend_resume + 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
101 safepoint = leaf + 10,
a61af66fc99e Initial load
duke
parents:
diff changeset
102 barrier = safepoint + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
103 nonleaf = barrier + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
104 max_nonleaf = nonleaf + 900,
a61af66fc99e Initial load
duke
parents:
diff changeset
105 native = max_nonleaf + 1
a61af66fc99e Initial load
duke
parents:
diff changeset
106 };
a61af66fc99e Initial load
duke
parents:
diff changeset
107
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // The WaitSet and EntryList linked lists are composed of ParkEvents.
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // I use ParkEvent instead of threads as ParkEvents are immortal and
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // type-stable, meaning we can safely unpark() a possibly stale
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // list element in the unlock()-path.
a61af66fc99e Initial load
duke
parents:
diff changeset
112
a61af66fc99e Initial load
duke
parents:
diff changeset
113 protected: // Monitor-Mutex metadata
a61af66fc99e Initial load
duke
parents:
diff changeset
114 SplitWord _LockWord ; // Contention queue (cxq) colocated with Lock-byte
a61af66fc99e Initial load
duke
parents:
diff changeset
115 enum LockWordBits { _LBIT=1 } ;
a61af66fc99e Initial load
duke
parents:
diff changeset
116 Thread * volatile _owner; // The owner of the lock
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // Consider sequestering _owner on its own $line
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // to aid future synchronization mechanisms.
a61af66fc99e Initial load
duke
parents:
diff changeset
119 ParkEvent * volatile _EntryList ; // List of threads waiting for entry
a61af66fc99e Initial load
duke
parents:
diff changeset
120 ParkEvent * volatile _OnDeck ; // heir-presumptive
a61af66fc99e Initial load
duke
parents:
diff changeset
121 volatile intptr_t _WaitLock [1] ; // Protects _WaitSet
a61af66fc99e Initial load
duke
parents:
diff changeset
122 ParkEvent * volatile _WaitSet ; // LL of ParkEvents
a61af66fc99e Initial load
duke
parents:
diff changeset
123 volatile bool _snuck; // Used for sneaky locking (evil).
a61af66fc99e Initial load
duke
parents:
diff changeset
124 int NotifyCount ; // diagnostic assist
55
2a8eb116ebbe 6610420: Debug VM crashes during monitor lock rank checking
xlu
parents: 0
diff changeset
125 char _name[MONITOR_NAME_LEN]; // Name of mutex
0
a61af66fc99e Initial load
duke
parents:
diff changeset
126
a61af66fc99e Initial load
duke
parents:
diff changeset
127 // Debugging fields for naming, deadlock detection, etc. (some only used in debug mode)
a61af66fc99e Initial load
duke
parents:
diff changeset
128 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
129 bool _allow_vm_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
130 debug_only(int _rank;) // rank (to avoid/detect potential deadlocks)
a61af66fc99e Initial load
duke
parents:
diff changeset
131 debug_only(Monitor * _next;) // Used by a Thread to link up owned locks
a61af66fc99e Initial load
duke
parents:
diff changeset
132 debug_only(Thread* _last_owner;) // the last thread to own the lock
a61af66fc99e Initial load
duke
parents:
diff changeset
133 debug_only(static bool contains(Monitor * locks, Monitor * lock);)
a61af66fc99e Initial load
duke
parents:
diff changeset
134 debug_only(static Monitor * get_least_ranked_lock(Monitor * locks);)
a61af66fc99e Initial load
duke
parents:
diff changeset
135 debug_only(Monitor * get_least_ranked_lock_besides_this(Monitor * locks);)
a61af66fc99e Initial load
duke
parents:
diff changeset
136 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
137
a61af66fc99e Initial load
duke
parents:
diff changeset
138 void set_owner_implementation(Thread* owner) PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
139 void check_prelock_state (Thread* thread) PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
140 void check_block_state (Thread* thread) PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
141
a61af66fc99e Initial load
duke
parents:
diff changeset
142 // platform-dependent support code can go here (in os_<os_family>.cpp)
a61af66fc99e Initial load
duke
parents:
diff changeset
143 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
144 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
145 _no_safepoint_check_flag = true,
a61af66fc99e Initial load
duke
parents:
diff changeset
146 _allow_vm_block_flag = true,
a61af66fc99e Initial load
duke
parents:
diff changeset
147 _as_suspend_equivalent_flag = true
a61af66fc99e Initial load
duke
parents:
diff changeset
148 };
a61af66fc99e Initial load
duke
parents:
diff changeset
149
a61af66fc99e Initial load
duke
parents:
diff changeset
150 enum WaitResults {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 CONDVAR_EVENT, // Wait returned because of condition variable notification
a61af66fc99e Initial load
duke
parents:
diff changeset
152 INTERRUPT_EVENT, // Wait returned because waiting thread was interrupted
a61af66fc99e Initial load
duke
parents:
diff changeset
153 NUMBER_WAIT_RESULTS
a61af66fc99e Initial load
duke
parents:
diff changeset
154 };
a61af66fc99e Initial load
duke
parents:
diff changeset
155
a61af66fc99e Initial load
duke
parents:
diff changeset
156 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
157 int TrySpin (Thread * Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
158 int TryLock () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
159 int TryFast () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
160 int AcquireOrPush (ParkEvent * ev) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 void IUnlock (bool RelaxAssert) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
162 void ILock (Thread * Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
163 int IWait (Thread * Self, jlong timo);
a61af66fc99e Initial load
duke
parents:
diff changeset
164 int ILocked () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166 protected:
55
2a8eb116ebbe 6610420: Debug VM crashes during monitor lock rank checking
xlu
parents: 0
diff changeset
167 static void ClearMonitor (Monitor * m, const char* name = NULL) ;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
168 Monitor() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
169
a61af66fc99e Initial load
duke
parents:
diff changeset
170 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
171 Monitor(int rank, const char *name, bool allow_vm_block=false);
a61af66fc99e Initial load
duke
parents:
diff changeset
172 ~Monitor();
a61af66fc99e Initial load
duke
parents:
diff changeset
173
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // Wait until monitor is notified (or times out).
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // Defaults are to make safepoint checks, wait time is forever (i.e.,
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // zero), and not a suspend-equivalent condition. Returns true if wait
a61af66fc99e Initial load
duke
parents:
diff changeset
177 // times out; otherwise returns false.
a61af66fc99e Initial load
duke
parents:
diff changeset
178 bool wait(bool no_safepoint_check = !_no_safepoint_check_flag,
a61af66fc99e Initial load
duke
parents:
diff changeset
179 long timeout = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
180 bool as_suspend_equivalent = !_as_suspend_equivalent_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
181 bool notify();
a61af66fc99e Initial load
duke
parents:
diff changeset
182 bool notify_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
183
a61af66fc99e Initial load
duke
parents:
diff changeset
184
a61af66fc99e Initial load
duke
parents:
diff changeset
185 void lock(); // prints out warning if VM thread blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
186 void lock(Thread *thread); // overloaded with current thread
a61af66fc99e Initial load
duke
parents:
diff changeset
187 void unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
188 bool is_locked() const { return _owner != NULL; }
a61af66fc99e Initial load
duke
parents:
diff changeset
189
a61af66fc99e Initial load
duke
parents:
diff changeset
190 bool try_lock(); // Like lock(), but unblocking. It returns false instead
a61af66fc99e Initial load
duke
parents:
diff changeset
191
a61af66fc99e Initial load
duke
parents:
diff changeset
192 // Lock without safepoint check. Should ONLY be used by safepoint code and other code
a61af66fc99e Initial load
duke
parents:
diff changeset
193 // that is guaranteed not to block while running inside the VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
194 void lock_without_safepoint_check();
a61af66fc99e Initial load
duke
parents:
diff changeset
195 void lock_without_safepoint_check (Thread * Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
196
a61af66fc99e Initial load
duke
parents:
diff changeset
197 // Current owner - not not MT-safe. Can only be used to guarantee that
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // the current running thread owns the lock
a61af66fc99e Initial load
duke
parents:
diff changeset
199 Thread* owner() const { return _owner; }
a61af66fc99e Initial load
duke
parents:
diff changeset
200 bool owned_by_self() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
201
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // Support for JVM_RawMonitorEnter & JVM_RawMonitorExit. These can be called by
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // non-Java thread. (We should really have a RawMonitor abstraction)
a61af66fc99e Initial load
duke
parents:
diff changeset
204 void jvm_raw_lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
205 void jvm_raw_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
206 const char *name() const { return _name; }
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 void print_on_error(outputStream* st) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
209
a61af66fc99e Initial load
duke
parents:
diff changeset
210 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
211 void print_on(outputStream* st) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
212 void print() const { print_on(tty); }
a61af66fc99e Initial load
duke
parents:
diff changeset
213 debug_only(int rank() const { return _rank; })
a61af66fc99e Initial load
duke
parents:
diff changeset
214 bool allow_vm_block() { return _allow_vm_block; }
a61af66fc99e Initial load
duke
parents:
diff changeset
215
a61af66fc99e Initial load
duke
parents:
diff changeset
216 debug_only(Monitor *next() const { return _next; })
a61af66fc99e Initial load
duke
parents:
diff changeset
217 debug_only(void set_next(Monitor *next) { _next = next; })
a61af66fc99e Initial load
duke
parents:
diff changeset
218 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 void set_owner(Thread* owner) {
a61af66fc99e Initial load
duke
parents:
diff changeset
221 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
222 set_owner_implementation(owner);
a61af66fc99e Initial load
duke
parents:
diff changeset
223 debug_only(void verify_Monitor(Thread* thr));
a61af66fc99e Initial load
duke
parents:
diff changeset
224 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
225 _owner = owner;
a61af66fc99e Initial load
duke
parents:
diff changeset
226 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
228
a61af66fc99e Initial load
duke
parents:
diff changeset
229 };
a61af66fc99e Initial load
duke
parents:
diff changeset
230
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // Normally we'd expect Monitor to extend Mutex in the sense that a monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // constructed from pthreads primitives might extend a mutex by adding
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // a condvar and some extra metadata. In fact this was the case until J2SE7.
a61af66fc99e Initial load
duke
parents:
diff changeset
234 //
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // Currently, however, the base object is a monitor. Monitor contains all the
a61af66fc99e Initial load
duke
parents:
diff changeset
236 // logic for wait(), notify(), etc. Mutex extends monitor and restricts the
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // visiblity of wait(), notify(), and notify_all().
a61af66fc99e Initial load
duke
parents:
diff changeset
238 //
a61af66fc99e Initial load
duke
parents:
diff changeset
239 // Another viable alternative would have been to have Monitor extend Mutex and
a61af66fc99e Initial load
duke
parents:
diff changeset
240 // implement all the normal mutex and wait()-notify() logic in Mutex base class.
a61af66fc99e Initial load
duke
parents:
diff changeset
241 // The wait()-notify() facility would be exposed via special protected member functions
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // (e.g., _Wait() and _Notify()) in Mutex. Monitor would extend Mutex and expose wait()
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // as a call to _Wait(). That is, the public wait() would be a wrapper for the protected
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // _Wait().
a61af66fc99e Initial load
duke
parents:
diff changeset
245 //
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // An even better alternative is to simply eliminate Mutex:: and use Monitor:: instead.
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // After all, monitors are sufficient for Java-level synchronization. At one point in time
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // there may have been some benefit to having distinct mutexes and monitors, but that time
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // has past.
a61af66fc99e Initial load
duke
parents:
diff changeset
250 //
a61af66fc99e Initial load
duke
parents:
diff changeset
251 // The Mutex/Monitor design parallels that of Java-monitors, being based on
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // thread-specific park-unpark platform-specific primitives.
a61af66fc99e Initial load
duke
parents:
diff changeset
253
a61af66fc99e Initial load
duke
parents:
diff changeset
254
a61af66fc99e Initial load
duke
parents:
diff changeset
255 class Mutex : public Monitor { // degenerate Monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
256 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
257 Mutex (int rank, const char *name, bool allow_vm_block=false);
a61af66fc99e Initial load
duke
parents:
diff changeset
258 ~Mutex () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
259 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
260 bool notify () { ShouldNotReachHere(); return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
261 bool notify_all() { ShouldNotReachHere(); return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
262 bool wait (bool no_safepoint_check, long timeout, bool as_suspend_equivalent) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 ShouldNotReachHere() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
264 return false ;
a61af66fc99e Initial load
duke
parents:
diff changeset
265 }
a61af66fc99e Initial load
duke
parents:
diff changeset
266 };
a61af66fc99e Initial load
duke
parents:
diff changeset
267
a61af66fc99e Initial load
duke
parents:
diff changeset
268 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
269 * Per-thread blocking support for JSR166. See the Java-level
a61af66fc99e Initial load
duke
parents:
diff changeset
270 * Documentation for rationale. Basically, park acts like wait, unpark
a61af66fc99e Initial load
duke
parents:
diff changeset
271 * like notify.
a61af66fc99e Initial load
duke
parents:
diff changeset
272 *
a61af66fc99e Initial load
duke
parents:
diff changeset
273 * 6271289 --
a61af66fc99e Initial load
duke
parents:
diff changeset
274 * To avoid errors where an os thread expires but the JavaThread still
a61af66fc99e Initial load
duke
parents:
diff changeset
275 * exists, Parkers are immortal (type-stable) and are recycled across
a61af66fc99e Initial load
duke
parents:
diff changeset
276 * new threads. This parallels the ParkEvent implementation.
a61af66fc99e Initial load
duke
parents:
diff changeset
277 * Because park-unpark allow spurious wakeups it is harmless if an
a61af66fc99e Initial load
duke
parents:
diff changeset
278 * unpark call unparks a new thread using the old Parker reference.
a61af66fc99e Initial load
duke
parents:
diff changeset
279 *
a61af66fc99e Initial load
duke
parents:
diff changeset
280 * In the future we'll want to think about eliminating Parker and using
a61af66fc99e Initial load
duke
parents:
diff changeset
281 * ParkEvent instead. There's considerable duplication between the two
a61af66fc99e Initial load
duke
parents:
diff changeset
282 * services.
a61af66fc99e Initial load
duke
parents:
diff changeset
283 *
a61af66fc99e Initial load
duke
parents:
diff changeset
284 */
a61af66fc99e Initial load
duke
parents:
diff changeset
285
a61af66fc99e Initial load
duke
parents:
diff changeset
286 class Parker : public os::PlatformParker {
a61af66fc99e Initial load
duke
parents:
diff changeset
287 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
288 volatile int _counter ;
a61af66fc99e Initial load
duke
parents:
diff changeset
289 Parker * FreeNext ;
a61af66fc99e Initial load
duke
parents:
diff changeset
290 JavaThread * AssociatedWith ; // Current association
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
293 Parker() : PlatformParker() {
a61af66fc99e Initial load
duke
parents:
diff changeset
294 _counter = 0 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
295 FreeNext = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
296 AssociatedWith = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
298 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
299 ~Parker() { ShouldNotReachHere(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
300 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // For simplicity of interface with Java, all forms of park (indefinite,
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // relative, and absolute) are multiplexed into one call.
a61af66fc99e Initial load
duke
parents:
diff changeset
303 void park(bool isAbsolute, jlong time);
a61af66fc99e Initial load
duke
parents:
diff changeset
304 void unpark();
a61af66fc99e Initial load
duke
parents:
diff changeset
305
a61af66fc99e Initial load
duke
parents:
diff changeset
306 // Lifecycle operators
a61af66fc99e Initial load
duke
parents:
diff changeset
307 static Parker * Allocate (JavaThread * t) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
308 static void Release (Parker * e) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
309 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
310 static Parker * volatile FreeList ;
a61af66fc99e Initial load
duke
parents:
diff changeset
311 static volatile int ListLock ;
a61af66fc99e Initial load
duke
parents:
diff changeset
312 };