summaryrefslogtreecommitdiffstats
path: root/luni-kernel/src
diff options
context:
space:
mode:
authorJesse Wilson <jessewilson@google.com>2009-07-16 11:56:27 -0700
committerJesse Wilson <jessewilson@google.com>2009-07-16 15:42:56 -0700
commite75fe375fff3928552ab6f6e1c9d4bb9a07e330d (patch)
treec9104d49addb53c8154b473af54f09556e2a969f /luni-kernel/src
parentff465236898c66c32813a048c45da500a22a0d7f (diff)
downloadlibcore-e75fe375fff3928552ab6f6e1c9d4bb9a07e330d.zip
libcore-e75fe375fff3928552ab6f6e1c9d4bb9a07e330d.tar.gz
libcore-e75fe375fff3928552ab6f6e1c9d4bb9a07e330d.tar.bz2
Fixing wakeups caused by Thread.join() interacting with LockSupport.unpark.
This caused several concurrency tests to fail when run with timeouts, since the tests cause park and unpark to happen frequently. Also fixing a tiny issue with CoreTestRunnable to use the proper tmp directory and to include the program of a failed external execution.
Diffstat (limited to 'luni-kernel/src')
-rw-r--r--luni-kernel/src/main/java/java/lang/Thread.java60
1 files changed, 49 insertions, 11 deletions
diff --git a/luni-kernel/src/main/java/java/lang/Thread.java b/luni-kernel/src/main/java/java/lang/Thread.java
index 3cde7e1..89d7ed6 100644
--- a/luni-kernel/src/main/java/java/lang/Thread.java
+++ b/luni-kernel/src/main/java/java/lang/Thread.java
@@ -73,6 +73,8 @@ import org.apache.harmony.security.fortress.SecurityUtils;
*/
public class Thread implements Runnable {
+ private static final int NANOS_PER_MILLI = 1000000;
+
/** Park states */
private static class ParkState {
/** park state indicating unparked */
@@ -973,7 +975,16 @@ public class Thread implements Runnable {
* @since Android 1.0
*/
public final void join() throws InterruptedException {
- join(0, 0);
+ VMThread t = vmThread;
+ if (t == null) {
+ return;
+ }
+
+ synchronized (t) {
+ while (isAlive()) {
+ t.wait();
+ }
+ }
}
/**
@@ -1008,18 +1019,45 @@ public class Thread implements Runnable {
* @since Android 1.0
*/
public final void join(long millis, int nanos) throws InterruptedException {
- if (millis < 0 || nanos < 0 || nanos > 999999) {
+ if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) {
throw new IllegalArgumentException();
}
- VMThread t;
+ // avoid overflow: if total > 292,277 years, just wait forever
+ boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI;
+ boolean forever = (millis | nanos) == 0;
+ if (forever | overflow) {
+ join();
+ return;
+ }
- t = this.vmThread;
+ VMThread t = vmThread;
+ if (t == null) {
+ return;
+ }
+
+ synchronized (t) {
+ if (!isAlive()) {
+ return;
+ }
+
+ // guaranteed not to overflow
+ long nanosToWait = millis * NANOS_PER_MILLI + nanos;
- if (t != null) {
- synchronized (t) {
- if (isAlive())
- t.wait(millis, nanos);
+ // wait until this thread completes or the timeout has elapsed
+ long start = System.nanoTime();
+ while (true) {
+ t.wait(millis, nanos);
+ if (!isAlive()) {
+ break;
+ }
+ long nanosElapsed = System.nanoTime() - start;
+ long nanosRemaining = nanosToWait - nanosElapsed;
+ if (nanosRemaining <= 0) {
+ break;
+ }
+ millis = nanosRemaining / NANOS_PER_MILLI;
+ nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI);
}
}
}
@@ -1491,8 +1529,8 @@ public class Thread implements Runnable {
break;
}
case ParkState.UNPARKED: {
- long millis = nanos / 1000000;
- nanos %= 1000000;
+ long millis = nanos / NANOS_PER_MILLI;
+ nanos %= NANOS_PER_MILLI;
parkState = ParkState.PARKED;
try {
@@ -1554,7 +1592,7 @@ public class Thread implements Runnable {
if (delayMillis <= 0) {
parkState = ParkState.UNPARKED;
} else {
- parkFor(delayMillis * 1000000);
+ parkFor(delayMillis * NANOS_PER_MILLI);
}
}
}