8241123: Refactor vmTestbase stress framework to use j.u.c and make creation of threads more flexible
Reviewed-by: iignatyev, sspitsyn
This commit is contained in:
parent
333a832cea
commit
e7204cbc52
test/hotspot/jtreg/vmTestbase/nsk
jdi/ObjectReference/referringObjects/referringObjects003
share
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,18 +27,27 @@ import java.util.*;
|
||||
import nsk.share.*;
|
||||
import nsk.share.jdi.HeapwalkingDebuggee;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/*
|
||||
* Test class handle request for start/stop test threads(threads are included in special thread group)
|
||||
*/
|
||||
public class referringObjects003a extends HeapwalkingDebuggee {
|
||||
|
||||
static AtomicBoolean shouldStop = new AtomicBoolean(false);
|
||||
|
||||
class TestThread implements Runnable {
|
||||
public void run() {
|
||||
wicket.waitFor();
|
||||
while(!shouldStop.get()) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// just wait for shouldStop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Wicket wicket = new Wicket();
|
||||
|
||||
private List<Thread> threads = new ArrayList<Thread>();
|
||||
|
||||
private List<ReferringObject> referrers;
|
||||
@ -71,7 +80,7 @@ public class referringObjects003a extends HeapwalkingDebuggee {
|
||||
}
|
||||
|
||||
public void stopThreads() {
|
||||
wicket.unlockAll();
|
||||
shouldStop.set(true);
|
||||
|
||||
for (Thread testThread : threads) {
|
||||
try {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,6 +24,10 @@
|
||||
package nsk.share;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Wicket provides a means for one or more threads to suspend execution
|
||||
@ -60,6 +64,9 @@ public class Wicket {
|
||||
/** Wicket's string identifier */
|
||||
private String name = "";
|
||||
|
||||
private final Lock lock = new ReentrantLock();
|
||||
private final Condition condition = lock.newCondition();
|
||||
|
||||
/**
|
||||
* Construct a Wicket with only one closed lock.
|
||||
*/
|
||||
@ -106,18 +113,26 @@ public class Wicket {
|
||||
*
|
||||
* <p>Please note, that the method would ignore Thread.interrupt() requests.
|
||||
*/
|
||||
public synchronized void waitFor() {
|
||||
++waiters;
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %s: waitFor()\n", name);
|
||||
}
|
||||
public void waitFor() {
|
||||
long id = System.currentTimeMillis();
|
||||
|
||||
while (count > 0) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {}
|
||||
try {
|
||||
lock.lock();
|
||||
++waiters;
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %d %s: waitFor(). There are %d waiters totally now.\n", id, name, waiters);
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
try {
|
||||
condition.await();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
--waiters;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
--waiters;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,25 +165,35 @@ public class Wicket {
|
||||
* @return the number of closed locks
|
||||
* @throws IllegalArgumentException if timeout is less than 0
|
||||
*/
|
||||
public synchronized int waitFor(long timeout) {
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %s: waitFor(%d)\n", name, timeout);
|
||||
}
|
||||
|
||||
public int waitFor(long timeout) {
|
||||
if (timeout < 0)
|
||||
throw new IllegalArgumentException(
|
||||
"timeout value is negative: " + timeout);
|
||||
++waiters;
|
||||
long waitTime = timeout;
|
||||
long startTime = System.currentTimeMillis();
|
||||
while (count > 0 && waitTime > 0) {
|
||||
try {
|
||||
wait(waitTime);
|
||||
} catch (InterruptedException e) {}
|
||||
waitTime = timeout - (System.currentTimeMillis() - startTime);
|
||||
"timeout value is negative: " + timeout);
|
||||
|
||||
long id = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
lock.lock();
|
||||
++waiters;
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %d %s: waitFor(). There are %d waiters totally now.\n", id, name, waiters);
|
||||
}
|
||||
|
||||
long waitTime = timeout;
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
while (count > 0 && waitTime > 0) {
|
||||
try {
|
||||
condition.await(waitTime, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
waitTime = timeout - (System.currentTimeMillis() - startTime);
|
||||
}
|
||||
--waiters;
|
||||
return count;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
--waiters;
|
||||
return (count);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -182,17 +207,23 @@ public class Wicket {
|
||||
*
|
||||
* @throws IllegalStateException if there is no one closed lock
|
||||
*/
|
||||
public synchronized void unlock() {
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %s: unlock()\n", name);
|
||||
}
|
||||
public void unlock() {
|
||||
|
||||
if (count == 0)
|
||||
throw new IllegalStateException("locks are already open");
|
||||
try {
|
||||
lock.lock();
|
||||
if (count == 0)
|
||||
throw new IllegalStateException("locks are already open");
|
||||
|
||||
--count;
|
||||
if (count == 0) {
|
||||
notifyAll();
|
||||
--count;
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %s: unlock() the count is now %d\n", name, count);
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
condition.signalAll();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,13 +236,18 @@ public class Wicket {
|
||||
* this Wicket then they will be released and re-enabled for thread
|
||||
* scheduling purposes.
|
||||
*/
|
||||
public synchronized void unlockAll() {
|
||||
public void unlockAll() {
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %s: unlockAll()\n", name);
|
||||
}
|
||||
|
||||
count = 0;
|
||||
notifyAll();
|
||||
try {
|
||||
lock.lock();
|
||||
count = 0;
|
||||
condition.signalAll();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -220,10 +256,15 @@ public class Wicket {
|
||||
*
|
||||
* @return number of waiters
|
||||
*/
|
||||
public synchronized int getWaiters() {
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %s: getWaiters()\n", name);
|
||||
public int getWaiters() {
|
||||
try {
|
||||
lock.lock();
|
||||
if (debugOutput != null) {
|
||||
debugOutput.printf("Wicket %s: getWaiters()\n", name);
|
||||
}
|
||||
return waiters;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return waiters;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,6 +30,7 @@ import nsk.share.test.ExecutionController;
|
||||
import nsk.share.TestBug;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Helper to assist in running threads.
|
||||
@ -45,7 +46,7 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
private List<Runnable> runnables = new ArrayList<Runnable>();
|
||||
private List<ManagedThread> threads = new ArrayList<ManagedThread>();
|
||||
private Wicket wicket = new Wicket();
|
||||
private Wicket finished;
|
||||
private AtomicInteger finished;
|
||||
private boolean started = false;
|
||||
private boolean successful = true;
|
||||
|
||||
@ -61,31 +62,49 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
private class ManagedThread extends Thread {
|
||||
private static class ManagedThreadFactory {
|
||||
|
||||
private RunParams params;
|
||||
|
||||
static ManagedThreadFactory createFactory(RunParams params) {
|
||||
return new ManagedThreadFactory(params);
|
||||
}
|
||||
|
||||
private ManagedThreadFactory(RunParams params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public Thread newThread(Runnable runnable, String name, int num) {
|
||||
return new Thread(runnable, name);
|
||||
}
|
||||
}
|
||||
|
||||
private class ManagedThread implements Runnable {
|
||||
|
||||
private Stresser stresser;
|
||||
private Throwable exception;
|
||||
private Runnable test;
|
||||
private boolean shouldWait;
|
||||
private Thread thread;
|
||||
|
||||
public ManagedThread(Runnable test) {
|
||||
super(test.toString());
|
||||
|
||||
public ManagedThread(ManagedThreadFactory threadFactory, Runnable test, int num) {
|
||||
this.test = test;
|
||||
this.shouldWait = true;
|
||||
this.stresser = new Stresser(this.getName(), runParams.getStressOptions());
|
||||
this.thread = threadFactory.newThread(this, test.toString(), num);
|
||||
this.stresser = new Stresser(thread.getName(), runParams.getStressOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
wicket.waitFor();
|
||||
try {
|
||||
stresser.start(runParams.getIterations());
|
||||
while (!this.isInterrupted() && stresser.iteration()) {
|
||||
while (!this.thread.isInterrupted() && stresser.iteration()) {
|
||||
test.run();
|
||||
Thread.yield();
|
||||
}
|
||||
waitForOtherThreads();
|
||||
} catch (OutOfMemoryError oom) {
|
||||
waitForOtherThreads();
|
||||
if (test instanceof OOMStress) {
|
||||
// Test stressing OOM, not a failure.
|
||||
log.info("Caught OutOfMemoryError in OOM stress test, omitting exception.");
|
||||
@ -93,9 +112,9 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
failWithException(oom);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
waitForOtherThreads();
|
||||
failWithException(t);
|
||||
} finally {
|
||||
waitForOtherThreads();
|
||||
stresser.finish();
|
||||
}
|
||||
}
|
||||
@ -103,8 +122,13 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
private void waitForOtherThreads() {
|
||||
if (shouldWait) {
|
||||
shouldWait = false;
|
||||
finished.unlock();
|
||||
finished.waitFor();
|
||||
finished.decrementAndGet();
|
||||
while (finished.get() != 0) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new TestBug("Waiting a second time is not premitted");
|
||||
}
|
||||
@ -121,7 +145,7 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
stresser.forceFinish();
|
||||
if (runParams.isInterruptThreads()) {
|
||||
log.debug("Interrupting: " + this);
|
||||
this.interrupt();
|
||||
this.thread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +175,7 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
}
|
||||
|
||||
public Thread getThread(int index) {
|
||||
return threads.get(index);
|
||||
return threads.get(index).thread;
|
||||
}
|
||||
|
||||
private int getCount() {
|
||||
@ -163,9 +187,10 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
|
||||
private void create() {
|
||||
int threadCount = runnables.size();
|
||||
finished = new Wicket(threadCount);
|
||||
finished = new AtomicInteger(threadCount);
|
||||
ManagedThreadFactory factory = ManagedThreadFactory.createFactory(runParams);
|
||||
for (int i = 0; i < threadCount; ++i) {
|
||||
threads.add(new ManagedThread(get(i)));
|
||||
threads.add(new ManagedThread(factory, get(i), i));
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,7 +204,7 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
create();
|
||||
prepare();
|
||||
for (int i = 0; i < threads.size(); ++i) {
|
||||
Thread t = (Thread) threads.get(i);
|
||||
Thread t = threads.get(i).thread;
|
||||
log.debug("Starting " + t);
|
||||
t.start();
|
||||
}
|
||||
@ -203,7 +228,7 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
*/
|
||||
public void join() throws InterruptedException {
|
||||
for (int i = 0; i < threads.size(); ++i) {
|
||||
Thread t = (Thread) threads.get(i);
|
||||
Thread t = threads.get(i).thread;
|
||||
//log.debug("Joining " + t);
|
||||
t.join();
|
||||
}
|
||||
@ -231,7 +256,7 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
|
||||
private ManagedThread findManagedThread(Thread t) {
|
||||
for (int i = 0; i < threads.size(); i++) {
|
||||
ManagedThread mt = threads.get(i);
|
||||
if (mt == t) {
|
||||
if (mt.thread == t) {
|
||||
return mt;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user