--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/jni/jnistress007.java Thu May 17 16:21:27 2018 -0700
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2007, 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * jnistress007 is a class that sets up classes that do the work
+ * for the test.
+ *
+ * The Interrupter objects send interrupts to the JNIters.
+ * The GarbageGenerator objects generate garbage.
+ *
+ * sync[0] synchronizes the test cycles.
+ * sync[1] synchronizes access to exception counters.
+ * sync[2] synchronizes the cycle count update. It also insures that
+ * the interrupts do not interfere with the cycle count updates.
+ * This is because cycle count updates are used to define cycles.
+ */
+
+
+/*
+ * @test
+ * @key stress
+ *
+ * @summary converted from VM testbase nsk/stress/jni/jnistress007.
+ * VM testbase keywords: [stress, quick, feature_283, nonconcurrent]
+ *
+ * @library /vmTestbase
+ * /test/lib
+ * @run driver jdk.test.lib.FileInstaller . .
+ * @run main/othervm/native
+ * nsk.stress.jni.jnistress007
+ * -numTHREADer 10
+ * -threadInterval 20
+ * -numInterrupter 2
+ * -interruptInterval 50
+ * -numGarbage 80
+ * -garbageInterval 5
+ * -numIteration 130
+ */
+
+package nsk.stress.jni;
+
+import nsk.share.Consts;
+import nsk.share.Debug;
+import nsk.share.test.StressOptions;
+
+public class jnistress007 extends Thread {
+
+ /* Maximum number of iterations. Ignored if <= 0L */
+ static long numIteration = 0L;
+ /* Timeout */
+ static long timeOut;
+ /* Number of test class objects */
+ static int numJNIter = 1;
+ /* Time between JNI stressing by the threads under test */
+ /* (in milliseconds) */
+ static int jniInterval = 10000;
+ /* Number of interrupting threads */
+ static int numInterrupter = 1;
+ /* Time between interrupts in milliseconds */
+ static int interruptInterval = 1000;
+ /* Number of garbage generating threads */
+ static int numGarbage = 1;
+ /* Time between garbage allocations in milliseconds */
+ static int garbageInterval = 1000;
+ // The MAX quantity of monitor's call
+ static int jniStringAllocSize = 300;
+
+ private static StressOptions stressOptions;
+
+ public static void main(String[] argv) {
+ try {
+ int i = 0;
+ int nJNISync = 10;
+ jnistress007 dm = null;
+ boolean errArg = false;
+
+ stressOptions = new StressOptions(argv);
+
+ /* Process arguments */
+ while (!errArg && i < argv.length) {
+ /* Number of iterations. Ignored if <= 0. */
+ if (i < argv.length && argv[i].equals("-numIteration")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ numIteration = Long.parseLong(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ }
+ } else if (i < argv.length && argv[i].equals("-numTHREADer")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ numJNIter = Integer.parseInt(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ if (numJNIter <= 0) errArg = true;
+ }
+ } else if (i < argv.length && argv[i].equals("-threadInterval")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ jniInterval = Integer.parseInt(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ }
+ } else if (i < argv.length && argv[i].equals("-numInterrupter")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ numInterrupter = Integer.parseInt(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ }
+ } else if (i < argv.length && argv[i].equals("-interruptInterval")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ interruptInterval = Integer.parseInt(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ }
+ } else if (i < argv.length && argv[i].equals("-numGarbage")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ numGarbage = Integer.parseInt(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ }
+ } else if (i < argv.length && argv[i].equals("-garbageInterval")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ garbageInterval = Integer.parseInt(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ }
+ } else if (i < argv.length && argv[i].equals("-jniStringAllocSize")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ try {
+ jniStringAllocSize = Integer.parseInt(argv[i++]);
+ } catch (NumberFormatException e) {
+ errArg = true;
+ }
+ }
+ } else if (i < argv.length && argv[i].startsWith("-stress")) {
+ ++i;
+ if (i < argv.length && Character.isDigit(argv[i].charAt(0))) {
+ ++i;
+ }
+ } else System.out.println("Argument #" + i++ + " is incorrect");
+ }
+
+ numIteration *= stressOptions.getIterationsFactor();
+ numJNIter *= stressOptions.getThreadsFactor();
+ numInterrupter *= stressOptions.getThreadsFactor();
+ numGarbage *= stressOptions.getThreadsFactor();
+ timeOut = stressOptions.getTime() * 1000;
+
+ sync = new Synchronizer[10];
+ for (i = 0; i < nJNISync; i++)
+ sync[i] = new Synchronizer();
+ dm = new jnistress007(numIteration, numJNIter, jniInterval,
+ numInterrupter, interruptInterval, numGarbage, garbageInterval);
+ dm.start();
+
+ try {
+ dm.join(timeOut);
+ } catch (InterruptedException e) {
+ System.out.println("TESTER THREAD WAS INTERRUPTED");
+ System.exit(Consts.TEST_FAILED);
+ }
+
+ if (DEBUG) System.out.println("jnistress007::main(): halt!");
+
+ if (dm.isAlive()) {
+ System.out.println("TIME LIMIT EXCEEDED");
+ dm.halt();
+ if (DEBUG) System.out.println("jnistress007::main(): join!");
+ try {
+ dm.join(10000L);
+ } catch (InterruptedException e) {
+ System.out.println("TESTER THREAD WAS INTERRUPTED");
+ System.exit(Consts.TEST_FAILED);
+ }
+ } else {
+ System.out.println("TESTER THREAD FINISHED");
+ }
+
+ if (DEBUG) System.out.println("jnistress007::main(): zzzz...");
+
+ if (JNIter007.passed())
+ System.exit(Consts.TEST_FAILED);
+
+ } catch (Throwable e) {
+ Debug.Fail(e);
+ }
+ }
+
+ jnistress007(
+ long iters,
+ int nJNI,
+ int jniInterval,
+ int nInter,
+ int iruptInterval,
+ int nGarb,
+ int garbInterval
+ ) {
+ int i = 0;
+ nCycles = iters;
+ /* Should have at least one of nCycles>0 */
+ if (nCycles <= 0) nCycles = Long.MAX_VALUE;
+ jniter = new JNIter007[nJNI];
+ interval = jniInterval;
+ irupt = new Interrupter[nInter];
+ garb = new GarbageGenerator[nGarb];
+ for (i = 0; i < nJNI; i++)
+ jniter[i] = new JNIter007(sync);
+ for (i = 0; i < nInter; i++) {
+ irupt[i] = new Interrupter(jniter, sync);
+ irupt[i].setInterval(iruptInterval);
+ }
+ for (i = 0; i < nGarb; i++) {
+ garb[i] = new GarbageGenerator();
+ garb[i].setInterval(garbInterval);
+ }
+ }
+
+ public void run() {
+ try {
+ int i = 0;
+ long iCycle = 0L;
+ JNIter007.clearCount();
+ JNIter007.clearInterruptCount();
+ for (i = 0; i < jniter.length; i++)
+ jniter[i].start();
+
+ while (JNIter007.getCount() < jniter.length) {
+ try {
+ sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ JNIter007.clearCount();
+ // JNIter007.clearInterruptCount();
+ synchronized (sync[0]) {
+ sync[0].notifyAll();
+ }
+
+ for (i = 0; i < garb.length; i++)
+ garb[i].start();
+ for (i = 0; i < irupt.length; i++)
+ irupt[i].start();
+
+ if (DEBUG) System.out.println("Cycles=" + nCycles);
+ for (iCycle = 0; iCycle < nCycles && !done && !JNIter007.passed(); iCycle++) {
+ System.out.print("Cycle: " + iCycle);
+ try {
+ sleep(interval);
+ } catch (InterruptedException e) {
+ }
+ synchronized (sync[1]) {
+ System.out.println("\tInterrupt count=" +
+ JNIter007.getInterruptCount());
+ }
+ JNIter007.clearCount();
+ synchronized (sync[0]) {
+ sync[0].notifyAll();
+ }
+ int n = 0;
+ for (i = 0; i < jniter.length; i++)
+ if (jniter[i].finished()) n++;
+ if (n == jniter.length) break;
+ }
+ for (i = 0; i < irupt.length; i++)
+ irupt[i].halt();
+ for (i = 0; i < garb.length; i++)
+ garb[i].halt();
+ for (i = 0; i < jniter.length; i++)
+ jniter[i].halt();
+ /* Flush any waiters */
+ if (DEBUG) System.out.println("jnistress007::run(): before sync[0]");
+ synchronized (sync[0]) {
+ sync[0].notifyAll();
+ }
+ if (DEBUG) System.out.println("jnistress007::run(): after sync[0]");
+ for (i = 0; i < irupt.length; i++) {
+ try {
+ irupt[i].join();
+ } catch (InterruptedException e) {
+ }
+ }
+ if (DEBUG) System.out.println("jnistress007::run(): X");
+ for (i = 0; i < garb.length; i++) {
+ try {
+ garb[i].join();
+ } catch (InterruptedException e) {
+ }
+ }
+ if (DEBUG) System.out.println("jnistress007::run(): Y");
+ synchronized (sync[0]) {
+ sync[0].notifyAll();
+ }
+ for (i = 0; i < jniter.length; i++) {
+ try {
+ jniter[i].join();
+ } catch (InterruptedException e) {
+ }
+ }
+ if (JNIter007.passed()) {
+ System.out.println("JNI TEST PASSED");
+ } else {
+ System.out.println("JNI TEST FAILED");
+ }
+ if (DEBUG) System.out.println("jnistress007::run(): Z");
+ } catch (Throwable e) {
+ Debug.Fail(e);
+ }
+ }
+
+ public void halt() {
+ done = true;
+ }
+
+ public boolean finished() {
+ return done;
+ }
+
+ long nCycles = 0;
+ JNIter007[] jniter;
+ static Synchronizer[] sync;
+ private int interval = 100;
+ Interrupter[] irupt;
+ GarbageGenerator[] garb;
+ private boolean done = false;
+ final private static boolean DEBUG = false;
+}
+
+class JNIter007 extends Thread {
+
+ // The native methods for testing JNI monitors calls
+ public native void incCount(String name);
+
+ static {
+ System.loadLibrary("jnistress007");
+ }
+
+ public static int nativeCount, javaCount = 0;
+
+ public JNIter007(Synchronizer[] aSync) {
+ sync = aSync;
+ }
+
+ public void run() {
+ try {
+ int iter = 0;
+
+ /* Synchronize start of work */
+ incCount();
+ synchronized (sync[0]) {
+ try {
+ sync[0].wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ while (!done && !pass) {
+ try {
+ /* Synchronized the JNI stressing */
+ synchronized (sync[2]) {
+ incCount();
+ }
+ synchronized (sync[0]) {
+ try {
+ sync[0].wait();
+ } catch (InterruptedException e) {
+ synchronized (sync[1]) {
+ JNIter007.incInterruptCount();
+ }
+ }
+ }
+ synchronized (sync[0]) {
+ try {
+ if ((javaCount < jnistress007.jniStringAllocSize) &&
+ (nativeCount < jnistress007.jniStringAllocSize)) {
+ javaCount++;
+ incCount(getName());
+ if ((javaCount % 1000) == 0)
+ System.out.println("Count in java " +
+ getName() + " " + javaCount);
+ } else if (javaCount == nativeCount) {
+ done = true;
+ } else {
+ System.out.println("Native: " + nativeCount +
+ "\t" + "Java: " + javaCount);
+ pass = true;
+ }
+ } catch (Exception e) {
+ System.out.println("Error: " + e);
+ }
+ }
+ if (DEBUG)
+ System.out.println("We have " + activeCount() + " threads now.");
+ synchronized (this) {
+ try {
+ wait(1L);
+ } catch (InterruptedException e) {
+ throw new InterruptedException();
+ }
+ }
+ } catch (Exception e) {
+ synchronized (sync[1]) {
+ JNIter007.incInterruptCount();
+ }
+ }
+ iter++;
+ iter = iter % CASECOUNT;
+ }
+ if (DEBUG) System.out.println("JNITer::run(): done=" + done);
+ done = true;
+ if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter007.pass);
+ if (DEBUG) System.out.println("JNIter::run(): done");
+ } catch (Throwable e) {
+ Debug.Fail(e);
+ }
+ }
+
+ private synchronized static void incCount() {
+ count++;
+ }
+
+ public static int getCount() {
+ return count;
+ }
+
+ public synchronized static void clearCount() {
+ count = 0;
+ }
+
+ private synchronized static void incInterruptCount() {
+ interruptCount++;
+ }
+
+ public static int getInterruptCount() {
+ return interruptCount;
+ }
+
+ public synchronized static void clearInterruptCount() {
+ interruptCount = 0;
+ }
+
+ public void halt() {
+ done = true;
+ }
+
+ public boolean finished() {
+ return done;
+ }
+
+ public static boolean passed() {
+ return pass;
+ }
+
+ Synchronizer[] sync;
+ private static int count = 0;
+ private static int interruptCount = 0;
+ private boolean done = false;
+ private static boolean pass = false;
+ final private static int CASECOUNT = 2;
+ final private static boolean DEBUG = false;
+}