111 |
|
* http://hdl.handle.net/1802/2104 |
112 |
|
*/ |
113 |
|
|
114 |
+ |
/** The number of CPUs, for sizing and spin control */ |
115 |
+ |
static final int NCPUS = Runtime.getRuntime().availableProcessors(); |
116 |
+ |
|
117 |
|
/** |
118 |
|
* Size of collision space. Using a size of half the number of |
119 |
|
* CPUs provides enough space for threads to find each other but |
121 |
|
* out to become unstuck. Note that the arena array holds SIZE+1 |
122 |
|
* elements, to include the top-of-stack slot. |
123 |
|
*/ |
124 |
< |
private static final int SIZE = |
125 |
< |
(Runtime.getRuntime().availableProcessors() + 1) / 2; |
124 |
> |
private static final int SIZE = (NCPUS + 1) / 2; |
125 |
> |
|
126 |
> |
/** |
127 |
> |
* The number of times to spin before blocking in timed waits. |
128 |
> |
* The value is empirically derived -- it works well across a |
129 |
> |
* variety of processors and OSes. Empirically, the best value |
130 |
> |
* seems not to vary with number of CPUs (beyond 2) so is just |
131 |
> |
* a constant. |
132 |
> |
*/ |
133 |
> |
static final int maxTimedSpins = (NCPUS < 2)? 0 : 16; |
134 |
> |
|
135 |
> |
/** |
136 |
> |
* The number of times to spin before blocking in untimed waits. |
137 |
> |
* This is greater than timed value because untimed waits spin |
138 |
> |
* faster since they don't need to check times on each spin. |
139 |
> |
*/ |
140 |
> |
static final int maxUntimedSpins = maxTimedSpins * 32; |
141 |
> |
|
142 |
> |
/** |
143 |
> |
* The number of nanoseconds for which it is faster to spin |
144 |
> |
* rather than to use timed park. A rough estimate suffices. |
145 |
> |
*/ |
146 |
> |
static final long spinForTimeoutThreshold = 1000L; |
147 |
|
|
148 |
|
/** |
149 |
|
* Base unit in nanoseconds for backoffs. Must be a power of two. |
295 |
|
*/ |
296 |
|
Object waitForHole(boolean timed, long nanos) { |
297 |
|
long lastTime = timed ? System.nanoTime() : 0; |
298 |
+ |
int spins = timed? maxTimedSpins : maxUntimedSpins; |
299 |
|
Object h; |
300 |
|
while ((h = get()) == null) { |
301 |
|
// If interrupted or timed out, try to cancel by |
304 |
|
(timed && nanos <= 0)) { |
305 |
|
if (compareAndSet(null, FAIL)) |
306 |
|
return FAIL; |
307 |
< |
} |
308 |
< |
else if (!timed) |
309 |
< |
LockSupport.park(); |
310 |
< |
else { |
311 |
< |
LockSupport.parkNanos(nanos); |
312 |
< |
long now = System.nanoTime(); |
313 |
< |
nanos -= now - lastTime; |
314 |
< |
lastTime = now; |
307 |
> |
} else { |
308 |
> |
if (timed) { |
309 |
> |
long now = System.nanoTime(); |
310 |
> |
nanos -= now - lastTime; |
311 |
> |
lastTime = now; |
312 |
> |
} |
313 |
> |
if (spins > 0) |
314 |
> |
--spins; |
315 |
> |
else if (!timed) |
316 |
> |
LockSupport.park(); |
317 |
> |
else if (nanos > spinForTimeoutThreshold) |
318 |
> |
LockSupport.parkNanos(nanos); |
319 |
|
} |
320 |
|
} |
321 |
|
return h; |