Harden monitor tests against spurious wakeups.
The monitor tests (1930 - 1934) were slightly flakey due to spurious
wake-ups. This makes them less susceptible to the issue by making
threads go back to sleep if the wake-up seems spurious.
Test: ./test.py --host -j50
Test: stress --cpu 60
Test: while ./test/run-test --host 1933; do; done
Change-Id: I895827e6433f9ab3d2bd5cc3bf10ad0e242ac89d
diff --git a/test/1930-monitor-info/src/art/Monitors.java b/test/1930-monitor-info/src/art/Monitors.java
index b28a3ee..7fe2b60 100644
--- a/test/1930-monitor-info/src/art/Monitors.java
+++ b/test/1930-monitor-info/src/art/Monitors.java
@@ -36,12 +36,40 @@
public static class NamedLock {
public final String name;
+ private volatile int calledNotify;
public NamedLock(String name) {
this.name = name;
+ calledNotify = 0;
}
+
public String toString() {
return String.format("NamedLock[%s]", name);
}
+
+ public final void DoWait() throws Exception {
+ final int v = calledNotify;
+ while (v == calledNotify) {
+ wait();
+ }
+ }
+
+ public final void DoWait(long t) throws Exception {
+ final int v = calledNotify;
+ final long target = System.currentTimeMillis() + (t / 2);
+ while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) {
+ wait(t);
+ }
+ }
+
+ public final void DoNotifyAll() throws Exception {
+ calledNotify++;
+ notifyAll();
+ }
+
+ public final void DoNotify() throws Exception {
+ calledNotify++;
+ notify();
+ }
}
public static final class MonitorUsage {
@@ -91,7 +119,7 @@
public static class LockController {
private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT }
- public final Object lock;
+ public final NamedLock lock;
public final long timeout;
private final AtomicStampedReference<Action> action;
private volatile Thread runner = null;
@@ -100,10 +128,10 @@
private static final AtomicInteger cnt = new AtomicInteger(0);
private volatile Throwable exe;
- public LockController(Object lock) {
+ public LockController(NamedLock lock) {
this(lock, 10 * 1000);
}
- public LockController(Object lock, long timeout) {
+ public LockController(NamedLock lock, long timeout) {
this.lock = lock;
this.timeout = timeout;
this.action = new AtomicStampedReference(Action.HOLD, 0);
@@ -177,16 +205,16 @@
Thread.yield();
break;
case NOTIFY:
- lock.notify();
+ lock.DoNotify();
break;
case NOTIFY_ALL:
- lock.notifyAll();
+ lock.DoNotifyAll();
break;
case TIMED_WAIT:
- lock.wait(timeout);
+ lock.DoWait(timeout);
break;
case WAIT:
- lock.wait();
+ lock.DoWait();
break;
default:
throw new Error("Unknown action " + action);
diff --git a/test/1930-monitor-info/src/art/Test1930.java b/test/1930-monitor-info/src/art/Test1930.java
index a7fa1c7..ee03d73 100644
--- a/test/1930-monitor-info/src/art/Test1930.java
+++ b/test/1930-monitor-info/src/art/Test1930.java
@@ -96,7 +96,7 @@
printMonitorUsage(lk);
sem.release();
try {
- lk.wait();
+ lk.DoWait();
} catch (Exception e) {
throw new Error("Error waiting!", e);
}
@@ -107,7 +107,7 @@
sem.acquire();
synchronized (lk) {
printMonitorUsage(lk);
- lk.notifyAll();
+ lk.DoNotifyAll();
}
t.join();
printMonitorUsage(lk);
diff --git a/test/1931-monitor-events/src/art/Monitors.java b/test/1931-monitor-events/src/art/Monitors.java
index b28a3ee..7fe2b60 100644
--- a/test/1931-monitor-events/src/art/Monitors.java
+++ b/test/1931-monitor-events/src/art/Monitors.java
@@ -36,12 +36,40 @@
public static class NamedLock {
public final String name;
+ private volatile int calledNotify;
public NamedLock(String name) {
this.name = name;
+ calledNotify = 0;
}
+
public String toString() {
return String.format("NamedLock[%s]", name);
}
+
+ public final void DoWait() throws Exception {
+ final int v = calledNotify;
+ while (v == calledNotify) {
+ wait();
+ }
+ }
+
+ public final void DoWait(long t) throws Exception {
+ final int v = calledNotify;
+ final long target = System.currentTimeMillis() + (t / 2);
+ while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) {
+ wait(t);
+ }
+ }
+
+ public final void DoNotifyAll() throws Exception {
+ calledNotify++;
+ notifyAll();
+ }
+
+ public final void DoNotify() throws Exception {
+ calledNotify++;
+ notify();
+ }
}
public static final class MonitorUsage {
@@ -91,7 +119,7 @@
public static class LockController {
private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT }
- public final Object lock;
+ public final NamedLock lock;
public final long timeout;
private final AtomicStampedReference<Action> action;
private volatile Thread runner = null;
@@ -100,10 +128,10 @@
private static final AtomicInteger cnt = new AtomicInteger(0);
private volatile Throwable exe;
- public LockController(Object lock) {
+ public LockController(NamedLock lock) {
this(lock, 10 * 1000);
}
- public LockController(Object lock, long timeout) {
+ public LockController(NamedLock lock, long timeout) {
this.lock = lock;
this.timeout = timeout;
this.action = new AtomicStampedReference(Action.HOLD, 0);
@@ -177,16 +205,16 @@
Thread.yield();
break;
case NOTIFY:
- lock.notify();
+ lock.DoNotify();
break;
case NOTIFY_ALL:
- lock.notifyAll();
+ lock.DoNotifyAll();
break;
case TIMED_WAIT:
- lock.wait(timeout);
+ lock.DoWait(timeout);
break;
case WAIT:
- lock.wait();
+ lock.DoWait();
break;
default:
throw new Error("Unknown action " + action);
diff --git a/test/1932-monitor-events-misc/src/art/Monitors.java b/test/1932-monitor-events-misc/src/art/Monitors.java
index b28a3ee..7fe2b60 100644
--- a/test/1932-monitor-events-misc/src/art/Monitors.java
+++ b/test/1932-monitor-events-misc/src/art/Monitors.java
@@ -36,12 +36,40 @@
public static class NamedLock {
public final String name;
+ private volatile int calledNotify;
public NamedLock(String name) {
this.name = name;
+ calledNotify = 0;
}
+
public String toString() {
return String.format("NamedLock[%s]", name);
}
+
+ public final void DoWait() throws Exception {
+ final int v = calledNotify;
+ while (v == calledNotify) {
+ wait();
+ }
+ }
+
+ public final void DoWait(long t) throws Exception {
+ final int v = calledNotify;
+ final long target = System.currentTimeMillis() + (t / 2);
+ while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) {
+ wait(t);
+ }
+ }
+
+ public final void DoNotifyAll() throws Exception {
+ calledNotify++;
+ notifyAll();
+ }
+
+ public final void DoNotify() throws Exception {
+ calledNotify++;
+ notify();
+ }
}
public static final class MonitorUsage {
@@ -91,7 +119,7 @@
public static class LockController {
private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT }
- public final Object lock;
+ public final NamedLock lock;
public final long timeout;
private final AtomicStampedReference<Action> action;
private volatile Thread runner = null;
@@ -100,10 +128,10 @@
private static final AtomicInteger cnt = new AtomicInteger(0);
private volatile Throwable exe;
- public LockController(Object lock) {
+ public LockController(NamedLock lock) {
this(lock, 10 * 1000);
}
- public LockController(Object lock, long timeout) {
+ public LockController(NamedLock lock, long timeout) {
this.lock = lock;
this.timeout = timeout;
this.action = new AtomicStampedReference(Action.HOLD, 0);
@@ -177,16 +205,16 @@
Thread.yield();
break;
case NOTIFY:
- lock.notify();
+ lock.DoNotify();
break;
case NOTIFY_ALL:
- lock.notifyAll();
+ lock.DoNotifyAll();
break;
case TIMED_WAIT:
- lock.wait(timeout);
+ lock.DoWait(timeout);
break;
case WAIT:
- lock.wait();
+ lock.DoWait();
break;
default:
throw new Error("Unknown action " + action);
diff --git a/test/1933-monitor-current-contended/src/art/Monitors.java b/test/1933-monitor-current-contended/src/art/Monitors.java
index b28a3ee..7fe2b60 100644
--- a/test/1933-monitor-current-contended/src/art/Monitors.java
+++ b/test/1933-monitor-current-contended/src/art/Monitors.java
@@ -36,12 +36,40 @@
public static class NamedLock {
public final String name;
+ private volatile int calledNotify;
public NamedLock(String name) {
this.name = name;
+ calledNotify = 0;
}
+
public String toString() {
return String.format("NamedLock[%s]", name);
}
+
+ public final void DoWait() throws Exception {
+ final int v = calledNotify;
+ while (v == calledNotify) {
+ wait();
+ }
+ }
+
+ public final void DoWait(long t) throws Exception {
+ final int v = calledNotify;
+ final long target = System.currentTimeMillis() + (t / 2);
+ while (v == calledNotify && (t < 0 || System.currentTimeMillis() < target)) {
+ wait(t);
+ }
+ }
+
+ public final void DoNotifyAll() throws Exception {
+ calledNotify++;
+ notifyAll();
+ }
+
+ public final void DoNotify() throws Exception {
+ calledNotify++;
+ notify();
+ }
}
public static final class MonitorUsage {
@@ -91,7 +119,7 @@
public static class LockController {
private static enum Action { HOLD, RELEASE, NOTIFY, NOTIFY_ALL, WAIT, TIMED_WAIT }
- public final Object lock;
+ public final NamedLock lock;
public final long timeout;
private final AtomicStampedReference<Action> action;
private volatile Thread runner = null;
@@ -100,10 +128,10 @@
private static final AtomicInteger cnt = new AtomicInteger(0);
private volatile Throwable exe;
- public LockController(Object lock) {
+ public LockController(NamedLock lock) {
this(lock, 10 * 1000);
}
- public LockController(Object lock, long timeout) {
+ public LockController(NamedLock lock, long timeout) {
this.lock = lock;
this.timeout = timeout;
this.action = new AtomicStampedReference(Action.HOLD, 0);
@@ -177,16 +205,16 @@
Thread.yield();
break;
case NOTIFY:
- lock.notify();
+ lock.DoNotify();
break;
case NOTIFY_ALL:
- lock.notifyAll();
+ lock.DoNotifyAll();
break;
case TIMED_WAIT:
- lock.wait(timeout);
+ lock.DoWait(timeout);
break;
case WAIT:
- lock.wait();
+ lock.DoWait();
break;
default:
throw new Error("Unknown action " + action);
diff --git a/test/1933-monitor-current-contended/src/art/Test1933.java b/test/1933-monitor-current-contended/src/art/Test1933.java
index e21c395..194a043 100644
--- a/test/1933-monitor-current-contended/src/art/Test1933.java
+++ b/test/1933-monitor-current-contended/src/art/Test1933.java
@@ -34,9 +34,13 @@
controller1.waitForLockToBeHeld();
controller1.DoWait();
controller1.waitForNotifySleep();
- System.out.println("c1 is contending for monitor: " + controller1.getWorkerContendedMonitor());
+ // Spurious wakeups can hurt us here. Just retry until we get the result we expect. The test
+ // will timeout eventually.
+ Object mon = controller1.getWorkerContendedMonitor();
+ for (; mon == null; mon = controller1.getWorkerContendedMonitor()) { Thread.yield(); }
+ System.out.println("c1 is contending for monitor: " + mon);
synchronized (lk) {
- lk.notifyAll();
+ lk.DoNotifyAll();
}
controller1.DoUnlock();
}