/* * 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 * 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. */ /* * jnistress001 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/jnistress001. * VM testbase keywords: [stress, quick, feature_283, nonconcurrent] * * @library /vmTestbase * /test/lib * @run main/othervm/native * nsk.stress.jni.jnistress001 * -numTHREADer 20 * -threadInterval 200 * -numInterrupter 2 * -interruptInterval 500 * -numGarbage 80 * -garbageInterval 5 * -numIteration 200 */ package nsk.stress.jni; import nsk.share.Consts; import nsk.share.Debug; import nsk.share.test.StressOptions; public class jnistress001 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; // Size of string's array in native method static int jniStringAllocSize = 1000; // Print period for native method static int printPeriod = 200; private static StressOptions stressOptions; public static void main(String[] argv) { try { int i = 0; int nJNISync = 10; jnistress001 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].equals("-printperiod")) { ++i; if (i < argv.length && Character.isDigit(argv[i].charAt(0))) { try { printPeriod = 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 jnistress001(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("jnistress001::main(): halt!"); if (dm.isAlive()) { System.out.println("TIME LIMIT EXCEEDED"); dm.halt(); if (DEBUG) System.out.println("jnistress001::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("jnistress001::main(): zzzz..."); if (!JNIter001.passed()) System.exit(Consts.TEST_FAILED); } catch (Throwable e) { Debug.Fail(e); } } jnistress001( 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 JNIter001[nJNI]; interval = jniInterval; irupt = new Interrupter[nInter]; garb = new GarbageGenerator[nGarb]; for (i = 0; i < nJNI; i++) jniter[i] = new JNIter001(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() { int i = 0; long iCycle = 0L; JNIter001.clearCount(); JNIter001.clearInterruptCount(); for (i = 0; i < jniter.length; i++) jniter[i].start(); while (JNIter001.getCount() < jniter.length) { try { sleep(100); } catch (InterruptedException e) { } } JNIter001.clearCount(); // JNIter001.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 && JNIter001.passed(); iCycle++) { System.out.print("Cycle: " + iCycle); try { sleep(interval); } catch (InterruptedException e) { } synchronized (sync[1]) { System.out.println(" Interrupt count=" + JNIter001.getInterruptCount()); } JNIter001.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; } if (JNIter001.passed()) { /* Use of setpass was backwards */ System.out.println("JNI TEST PASSED"); } else { System.out.println("JNI TEST FAILED"); } 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("jnistress001::run(): before sync[0]"); synchronized (sync[0]) { sync[0].notifyAll(); } if (DEBUG) System.out.println("jnistress001::run(): after sync[0]"); for (i = 0; i < irupt.length; i++) { try { irupt[i].join(); } catch (InterruptedException e) { } } if (DEBUG) System.out.println("jnistress001::run(): X"); for (i = 0; i < garb.length; i++) { try { garb[i].join(); } catch (InterruptedException e) { } } if (DEBUG) System.out.println("jnistress001::run(): Y"); System.out.println("jniter.length is " + jniter.length); for (i = 0; i < jniter.length; i++) { try { if (jniter[i].isAlive()) { jniter[i].join(); } } catch (InterruptedException e) { } } if (DEBUG) System.out.println("jnistress001::run(): Z"); } public void halt() { done = true; } public boolean finished() { return done; } long nCycles = 0; JNIter001[] jniter; static Synchronizer[] sync; private int interval = 100; Interrupter[] irupt; GarbageGenerator[] garb; private boolean done = false; final private static boolean DEBUG = false; } class JNIter001 extends Thread { // The native method for testing JNI UTF-8 calls public native String jnistress(String threadName, int nstr, int printPeriod); // The native method for testing JNI Unicode calls public native String jnistress1(String threadName, int nstr, int printPeriod); static { System.loadLibrary("jnistress001"); } public JNIter001(Synchronizer[] aSync) { sync = aSync; } public void run() { 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]) { JNIter001.incInterruptCount(); } } } synchronized (sync[0]) { String s1 = jnistress(getName(), jnistress001.jniStringAllocSize, jnistress001.printPeriod); String s2 = jnistress1(getName(), jnistress001.jniStringAllocSize, jnistress001.printPeriod); if (!s1.equals(s2)) System.out.println("Wrong compare in thread " + getName()); } if (DEBUG) System.out.println("We have " + activeCount() + " threads now."); } catch (Exception e) { synchronized (sync[1]) { JNIter001.incInterruptCount(); } } iter++; iter = iter % CASECOUNT; } if (DEBUG) System.out.println("JNITer::run(): done=" + done); done = true; if (DEBUG) System.out.println("JNITer::run(): pass=" + JNIter001.pass); if (DEBUG) System.out.println("JNITer::run(): done"); } 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 static void halt() { done = true; } public boolean finished() { return done; } public static boolean passed() { return pass; } public static void setpass(boolean value) { pass = value; } Synchronizer[] sync; private static int count = 0; private static int interruptCount = 0; private static boolean done = false; private static boolean pass = true; final private static int CASECOUNT = 2; final private static boolean DEBUG = false; }