annotate src/share/vm/runtime/mutex.hpp @ 94:0834225a7916

6634032: CMS: Need CMSInitiatingPermOccupancyFraction for perm, divorcing from CMSInitiatingOccupancyFraction Summary: The option CMSInitiatingPermOccupancyFraction now controls perm triggering threshold. Even though the actual value of the threshold has not yet been changed, so there is no change in policy, we now have the infrastructure in place for dynamically deciding when to collect the perm gen, an issue that will be addressed in the near future. Reviewed-by: jmasa
author ysr
date Sun, 16 Mar 2008 21:57:25 -0700
parents a61af66fc99e
children 2a8eb116ebbe
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
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[]
a61af66fc99e Initial load
duke
parents:
diff changeset
64 #ifdef AMD64 // little
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 #if IA32 // little
a61af66fc99e Initial load
duke
parents:
diff changeset
68 #define _LSBINDEX 0
a61af66fc99e Initial load
duke
parents:
diff changeset
69 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
70 #ifdef SPARC // big
a61af66fc99e Initial load
duke
parents:
diff changeset
71 #define _LSBINDEX (sizeof(intptr_t)-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
72 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
73 #error "unknown architecture"
a61af66fc99e Initial load
duke
parents:
diff changeset
74 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
75 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
76 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 class ParkEvent ;
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 // See orderAccess.hpp. We assume throughout the VM that mutex lock and
a61af66fc99e Initial load
duke
parents:
diff changeset
81 // try_lock do fence-lock-acquire, and that unlock does a release-unlock,
a61af66fc99e Initial load
duke
parents:
diff changeset
82 // *in that order*. If their implementations change such that these
a61af66fc99e Initial load
duke
parents:
diff changeset
83 // assumptions are violated, a whole lot of code will break.
a61af66fc99e Initial load
duke
parents:
diff changeset
84
a61af66fc99e Initial load
duke
parents:
diff changeset
85 class Monitor : public CHeapObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
86
a61af66fc99e Initial load
duke
parents:
diff changeset
87 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // A special lock: Is a lock where you are guaranteed not to block while you are
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // holding it, i.e., no vm operation can happen, taking other locks, etc.
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // NOTE: It is critical that the rank 'special' be the lowest (earliest)
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // (except for "event"?) for the deadlock dection to work correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // The rank native is only for use in Mutex's created by JVM_RawMonitorCreate,
a61af66fc99e Initial load
duke
parents:
diff changeset
93 // which being external to the VM are not subject to deadlock detection.
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // The rank safepoint is used only for synchronization in reaching a
a61af66fc99e Initial load
duke
parents:
diff changeset
95 // safepoint and leaving a safepoint. It is only used for the Safepoint_lock
a61af66fc99e Initial load
duke
parents:
diff changeset
96 // currently. While at a safepoint no mutexes of rank safepoint are held
a61af66fc99e Initial load
duke
parents:
diff changeset
97 // by any thread.
a61af66fc99e Initial load
duke
parents:
diff changeset
98 // The rank named "leaf" is probably historical (and should
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // be changed) -- mutexes of this rank aren't really leaf mutexes
a61af66fc99e Initial load
duke
parents:
diff changeset
100 // at all.
a61af66fc99e Initial load
duke
parents:
diff changeset
101 enum lock_types {
a61af66fc99e Initial load
duke
parents:
diff changeset
102 event,
a61af66fc99e Initial load
duke
parents:
diff changeset
103 special,
a61af66fc99e Initial load
duke
parents:
diff changeset
104 suspend_resume,
a61af66fc99e Initial load
duke
parents:
diff changeset
105 leaf = suspend_resume + 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
106 safepoint = leaf + 10,
a61af66fc99e Initial load
duke
parents:
diff changeset
107 barrier = safepoint + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
108 nonleaf = barrier + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
109 max_nonleaf = nonleaf + 900,
a61af66fc99e Initial load
duke
parents:
diff changeset
110 native = max_nonleaf + 1
a61af66fc99e Initial load
duke
parents:
diff changeset
111 };
a61af66fc99e Initial load
duke
parents:
diff changeset
112
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // The WaitSet and EntryList linked lists are composed of ParkEvents.
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // I use ParkEvent instead of threads as ParkEvents are immortal and
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // type-stable, meaning we can safely unpark() a possibly stale
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // list element in the unlock()-path.
a61af66fc99e Initial load
duke
parents:
diff changeset
117
a61af66fc99e Initial load
duke
parents:
diff changeset
118 protected: // Monitor-Mutex metadata
a61af66fc99e Initial load
duke
parents:
diff changeset
119 SplitWord _LockWord ; // Contention queue (cxq) colocated with Lock-byte
a61af66fc99e Initial load
duke
parents:
diff changeset
120 enum LockWordBits { _LBIT=1 } ;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 Thread * volatile _owner; // The owner of the lock
a61af66fc99e Initial load
duke
parents:
diff changeset
122 // Consider sequestering _owner on its own $line
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // to aid future synchronization mechanisms.
a61af66fc99e Initial load
duke
parents:
diff changeset
124 ParkEvent * volatile _EntryList ; // List of threads waiting for entry
a61af66fc99e Initial load
duke
parents:
diff changeset
125 ParkEvent * volatile _OnDeck ; // heir-presumptive
a61af66fc99e Initial load
duke
parents:
diff changeset
126 volatile intptr_t _WaitLock [1] ; // Protects _WaitSet
a61af66fc99e Initial load
duke
parents:
diff changeset
127 ParkEvent * volatile _WaitSet ; // LL of ParkEvents
a61af66fc99e Initial load
duke
parents:
diff changeset
128 volatile bool _snuck; // Used for sneaky locking (evil).
a61af66fc99e Initial load
duke
parents:
diff changeset
129 const char * _name; // Name of mutex
a61af66fc99e Initial load
duke
parents:
diff changeset
130 int NotifyCount ; // diagnostic assist
a61af66fc99e Initial load
duke
parents:
diff changeset
131 double pad [8] ; // avoid false sharing
a61af66fc99e Initial load
duke
parents:
diff changeset
132
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // Debugging fields for naming, deadlock detection, etc. (some only used in debug mode)
a61af66fc99e Initial load
duke
parents:
diff changeset
134 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
135 bool _allow_vm_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
136 debug_only(int _rank;) // rank (to avoid/detect potential deadlocks)
a61af66fc99e Initial load
duke
parents:
diff changeset
137 debug_only(Monitor * _next;) // Used by a Thread to link up owned locks
a61af66fc99e Initial load
duke
parents:
diff changeset
138 debug_only(Thread* _last_owner;) // the last thread to own the lock
a61af66fc99e Initial load
duke
parents:
diff changeset
139 debug_only(static bool contains(Monitor * locks, Monitor * lock);)
a61af66fc99e Initial load
duke
parents:
diff changeset
140 debug_only(static Monitor * get_least_ranked_lock(Monitor * locks);)
a61af66fc99e Initial load
duke
parents:
diff changeset
141 debug_only(Monitor * get_least_ranked_lock_besides_this(Monitor * locks);)
a61af66fc99e Initial load
duke
parents:
diff changeset
142 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 void set_owner_implementation(Thread* owner) PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
145 void check_prelock_state (Thread* thread) PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
146 void check_block_state (Thread* thread) PRODUCT_RETURN;
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // platform-dependent support code can go here (in os_<os_family>.cpp)
a61af66fc99e Initial load
duke
parents:
diff changeset
149 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
150 enum {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 _no_safepoint_check_flag = true,
a61af66fc99e Initial load
duke
parents:
diff changeset
152 _allow_vm_block_flag = true,
a61af66fc99e Initial load
duke
parents:
diff changeset
153 _as_suspend_equivalent_flag = true
a61af66fc99e Initial load
duke
parents:
diff changeset
154 };
a61af66fc99e Initial load
duke
parents:
diff changeset
155
a61af66fc99e Initial load
duke
parents:
diff changeset
156 enum WaitResults {
a61af66fc99e Initial load
duke
parents:
diff changeset
157 CONDVAR_EVENT, // Wait returned because of condition variable notification
a61af66fc99e Initial load
duke
parents:
diff changeset
158 INTERRUPT_EVENT, // Wait returned because waiting thread was interrupted
a61af66fc99e Initial load
duke
parents:
diff changeset
159 NUMBER_WAIT_RESULTS
a61af66fc99e Initial load
duke
parents:
diff changeset
160 };
a61af66fc99e Initial load
duke
parents:
diff changeset
161
a61af66fc99e Initial load
duke
parents:
diff changeset
162 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
163 int TrySpin (Thread * Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
164 int TryLock () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
165 int TryFast () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
166 int AcquireOrPush (ParkEvent * ev) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 void IUnlock (bool RelaxAssert) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
168 void ILock (Thread * Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
169 int IWait (Thread * Self, jlong timo);
a61af66fc99e Initial load
duke
parents:
diff changeset
170 int ILocked () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
171
a61af66fc99e Initial load
duke
parents:
diff changeset
172 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
173 static void ClearMonitor (Monitor * m) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
174 Monitor() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
175
a61af66fc99e Initial load
duke
parents:
diff changeset
176 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
177 Monitor(int rank, const char *name, bool allow_vm_block=false);
a61af66fc99e Initial load
duke
parents:
diff changeset
178 ~Monitor();
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // Wait until monitor is notified (or times out).
a61af66fc99e Initial load
duke
parents:
diff changeset
181 // Defaults are to make safepoint checks, wait time is forever (i.e.,
a61af66fc99e Initial load
duke
parents:
diff changeset
182 // zero), and not a suspend-equivalent condition. Returns true if wait
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // times out; otherwise returns false.
a61af66fc99e Initial load
duke
parents:
diff changeset
184 bool wait(bool no_safepoint_check = !_no_safepoint_check_flag,
a61af66fc99e Initial load
duke
parents:
diff changeset
185 long timeout = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
186 bool as_suspend_equivalent = !_as_suspend_equivalent_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
187 bool notify();
a61af66fc99e Initial load
duke
parents:
diff changeset
188 bool notify_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
189
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191 void lock(); // prints out warning if VM thread blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
192 void lock(Thread *thread); // overloaded with current thread
a61af66fc99e Initial load
duke
parents:
diff changeset
193 void unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
194 bool is_locked() const { return _owner != NULL; }
a61af66fc99e Initial load
duke
parents:
diff changeset
195
a61af66fc99e Initial load
duke
parents:
diff changeset
196 bool try_lock(); // Like lock(), but unblocking. It returns false instead
a61af66fc99e Initial load
duke
parents:
diff changeset
197
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // Lock without safepoint check. Should ONLY be used by safepoint code and other code
a61af66fc99e Initial load
duke
parents:
diff changeset
199 // that is guaranteed not to block while running inside the VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
200 void lock_without_safepoint_check();
a61af66fc99e Initial load
duke
parents:
diff changeset
201 void lock_without_safepoint_check (Thread * Self) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
202
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // Current owner - not not MT-safe. Can only be used to guarantee that
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // the current running thread owns the lock
a61af66fc99e Initial load
duke
parents:
diff changeset
205 Thread* owner() const { return _owner; }
a61af66fc99e Initial load
duke
parents:
diff changeset
206 bool owned_by_self() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
207
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // Support for JVM_RawMonitorEnter & JVM_RawMonitorExit. These can be called by
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // non-Java thread. (We should really have a RawMonitor abstraction)
a61af66fc99e Initial load
duke
parents:
diff changeset
210 void jvm_raw_lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
211 void jvm_raw_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
212 const char *name() const { return _name; }
a61af66fc99e Initial load
duke
parents:
diff changeset
213
a61af66fc99e Initial load
duke
parents:
diff changeset
214 void print_on_error(outputStream* st) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
215
a61af66fc99e Initial load
duke
parents:
diff changeset
216 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
217 void print_on(outputStream* st) const;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 void print() const { print_on(tty); }
a61af66fc99e Initial load
duke
parents:
diff changeset
219 debug_only(int rank() const { return _rank; })
a61af66fc99e Initial load
duke
parents:
diff changeset
220 bool allow_vm_block() { return _allow_vm_block; }
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222 debug_only(Monitor *next() const { return _next; })
a61af66fc99e Initial load
duke
parents:
diff changeset
223 debug_only(void set_next(Monitor *next) { _next = next; })
a61af66fc99e Initial load
duke
parents:
diff changeset
224 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 void set_owner(Thread* owner) {
a61af66fc99e Initial load
duke
parents:
diff changeset
227 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
228 set_owner_implementation(owner);
a61af66fc99e Initial load
duke
parents:
diff changeset
229 debug_only(void verify_Monitor(Thread* thr));
a61af66fc99e Initial load
duke
parents:
diff changeset
230 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
231 _owner = owner;
a61af66fc99e Initial load
duke
parents:
diff changeset
232 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
234
a61af66fc99e Initial load
duke
parents:
diff changeset
235 };
a61af66fc99e Initial load
duke
parents:
diff changeset
236
a61af66fc99e Initial load
duke
parents:
diff changeset
237 // Normally we'd expect Monitor to extend Mutex in the sense that a monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // constructed from pthreads primitives might extend a mutex by adding
a61af66fc99e Initial load
duke
parents:
diff changeset
239 // a condvar and some extra metadata. In fact this was the case until J2SE7.
a61af66fc99e Initial load
duke
parents:
diff changeset
240 //
a61af66fc99e Initial load
duke
parents:
diff changeset
241 // Currently, however, the base object is a monitor. Monitor contains all the
a61af66fc99e Initial load
duke
parents:
diff changeset
242 // logic for wait(), notify(), etc. Mutex extends monitor and restricts the
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // visiblity of wait(), notify(), and notify_all().
a61af66fc99e Initial load
duke
parents:
diff changeset
244 //
a61af66fc99e Initial load
duke
parents:
diff changeset
245 // Another viable alternative would have been to have Monitor extend Mutex and
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // implement all the normal mutex and wait()-notify() logic in Mutex base class.
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // The wait()-notify() facility would be exposed via special protected member functions
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // (e.g., _Wait() and _Notify()) in Mutex. Monitor would extend Mutex and expose wait()
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // as a call to _Wait(). That is, the public wait() would be a wrapper for the protected
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // _Wait().
a61af66fc99e Initial load
duke
parents:
diff changeset
251 //
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // An even better alternative is to simply eliminate Mutex:: and use Monitor:: instead.
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // After all, monitors are sufficient for Java-level synchronization. At one point in time
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // there may have been some benefit to having distinct mutexes and monitors, but that time
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // has past.
a61af66fc99e Initial load
duke
parents:
diff changeset
256 //
a61af66fc99e Initial load
duke
parents:
diff changeset
257 // The Mutex/Monitor design parallels that of Java-monitors, being based on
a61af66fc99e Initial load
duke
parents:
diff changeset
258 // thread-specific park-unpark platform-specific primitives.
a61af66fc99e Initial load
duke
parents:
diff changeset
259
a61af66fc99e Initial load
duke
parents:
diff changeset
260
a61af66fc99e Initial load
duke
parents:
diff changeset
261 class Mutex : public Monitor { // degenerate Monitor
a61af66fc99e Initial load
duke
parents:
diff changeset
262 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
263 Mutex (int rank, const char *name, bool allow_vm_block=false);
a61af66fc99e Initial load
duke
parents:
diff changeset
264 ~Mutex () ;
a61af66fc99e Initial load
duke
parents:
diff changeset
265 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
266 bool notify () { ShouldNotReachHere(); return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
267 bool notify_all() { ShouldNotReachHere(); return false; }
a61af66fc99e Initial load
duke
parents:
diff changeset
268 bool wait (bool no_safepoint_check, long timeout, bool as_suspend_equivalent) {
a61af66fc99e Initial load
duke
parents:
diff changeset
269 ShouldNotReachHere() ;
a61af66fc99e Initial load
duke
parents:
diff changeset
270 return false ;
a61af66fc99e Initial load
duke
parents:
diff changeset
271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
272 };
a61af66fc99e Initial load
duke
parents:
diff changeset
273
a61af66fc99e Initial load
duke
parents:
diff changeset
274 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
275 * Per-thread blocking support for JSR166. See the Java-level
a61af66fc99e Initial load
duke
parents:
diff changeset
276 * Documentation for rationale. Basically, park acts like wait, unpark
a61af66fc99e Initial load
duke
parents:
diff changeset
277 * like notify.
a61af66fc99e Initial load
duke
parents:
diff changeset
278 *
a61af66fc99e Initial load
duke
parents:
diff changeset
279 * 6271289 --
a61af66fc99e Initial load
duke
parents:
diff changeset
280 * To avoid errors where an os thread expires but the JavaThread still
a61af66fc99e Initial load
duke
parents:
diff changeset
281 * exists, Parkers are immortal (type-stable) and are recycled across
a61af66fc99e Initial load
duke
parents:
diff changeset
282 * new threads. This parallels the ParkEvent implementation.
a61af66fc99e Initial load
duke
parents:
diff changeset
283 * Because park-unpark allow spurious wakeups it is harmless if an
a61af66fc99e Initial load
duke
parents:
diff changeset
284 * unpark call unparks a new thread using the old Parker reference.
a61af66fc99e Initial load
duke
parents:
diff changeset
285 *
a61af66fc99e Initial load
duke
parents:
diff changeset
286 * In the future we'll want to think about eliminating Parker and using
a61af66fc99e Initial load
duke
parents:
diff changeset
287 * ParkEvent instead. There's considerable duplication between the two
a61af66fc99e Initial load
duke
parents:
diff changeset
288 * services.
a61af66fc99e Initial load
duke
parents:
diff changeset
289 *
a61af66fc99e Initial load
duke
parents:
diff changeset
290 */
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 class Parker : public os::PlatformParker {
a61af66fc99e Initial load
duke
parents:
diff changeset
293 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
294 volatile int _counter ;
a61af66fc99e Initial load
duke
parents:
diff changeset
295 Parker * FreeNext ;
a61af66fc99e Initial load
duke
parents:
diff changeset
296 JavaThread * AssociatedWith ; // Current association
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
299 Parker() : PlatformParker() {
a61af66fc99e Initial load
duke
parents:
diff changeset
300 _counter = 0 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
301 FreeNext = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
302 AssociatedWith = NULL ;
a61af66fc99e Initial load
duke
parents:
diff changeset
303 }
a61af66fc99e Initial load
duke
parents:
diff changeset
304 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
305 ~Parker() { ShouldNotReachHere(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
306 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // For simplicity of interface with Java, all forms of park (indefinite,
a61af66fc99e Initial load
duke
parents:
diff changeset
308 // relative, and absolute) are multiplexed into one call.
a61af66fc99e Initial load
duke
parents:
diff changeset
309 void park(bool isAbsolute, jlong time);
a61af66fc99e Initial load
duke
parents:
diff changeset
310 void unpark();
a61af66fc99e Initial load
duke
parents:
diff changeset
311
a61af66fc99e Initial load
duke
parents:
diff changeset
312 // Lifecycle operators
a61af66fc99e Initial load
duke
parents:
diff changeset
313 static Parker * Allocate (JavaThread * t) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
314 static void Release (Parker * e) ;
a61af66fc99e Initial load
duke
parents:
diff changeset
315 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
316 static Parker * volatile FreeList ;
a61af66fc99e Initial load
duke
parents:
diff changeset
317 static volatile int ListLock ;
a61af66fc99e Initial load
duke
parents:
diff changeset
318 };