// $Archive:: $ // $Date: Mon, 23 Jun 2003 07:47:48 -0700 $ // $Revision: 1.3.1.2 $ // Description: Titanium synchronization tester // Copyright 2000, Dan Bonachea class Flag { private volatile int val; public Flag(int init) { val = init; } public Flag() { this(-1); } public void set(int val) { this.val = val; } public void set() { set(Ti.thisProc()); } public int get() { return val; } public void check(int val, String loc) { if (this.val != val) throw new InternalError("flag mismatch - illegal synchronization detected" + (loc.length() > 0 ? " (at " + loc : ")")); } // helpers public void check(int val) { check(val,""); } public void check(String loc) { check(Ti.thisProc(),loc); } public void check() { check(Ti.thisProc()); } } //------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------ public class synctest { private static Flag flag; //------------------------------------------------------------------------------------ // test class synchronized method public static void test1(int iters) { for (int i=0; i < iters; i++) { if (Ti.thisProc() == 0) { System.out.print("."); System.out.flush(); } test1sub(); } } private static synchronized void test1sub() { flag.set(); for (int i=0;i < 10;i++) { doWork(); flag.check(); } } //------------------------------------------------------------------------------------ // test object synchronized method public void test1b(int iters) { for (int i=0; i < iters; i++) { if (Ti.thisProc() == 0) { System.out.print("."); System.out.flush(); } test1bsub(); } } private synchronized void test1bsub() { flag.set(); for (int i=0;i < 10;i++) { doWork(); flag.check(); } } //------------------------------------------------------------------------------------ // test barrier public static void test2(int single iters) { boolean failed = false; // try to prevent barrier corruption of future tests for (int single i=0 ; i < iters ; i++) { if (Ti.thisProc() == 0) { System.out.print("."); System.out.flush(); } failed = test2sub(i) || failed; } if (failed) throwInternalError("delayed failure"); } private static boolean test2sub(int currflag) { boolean failed = false; flag.set(currflag); try { for (int i = 0; i < Ti.thisProc(); i++) { doWork(); flag.check(currflag); } } catch (Throwable exn) { failed = true; } Ti.barrier(); flag.set(-1); Ti.barrier(); return failed; } //------------------------------------------------------------------------------------ // test simple wait/notify public static Flag t3ahelp; public static void test3a(int single iters) { for (int single i = 0; i < iters; i++) { if (Ti.thisProc() == 0) { System.out.print("."); System.out.flush(); } test3asub(i); Ti.barrier(); } } public static int t3ajunk; private static void test3asub(int i) { if (Ti.thisProc() == 0) t3ahelp.set(0); Ti.barrier(); synchronized (flag) { flag.set(); doWork(); flag.check("entered sync"); try { if (t3ahelp.get() < Ti.numProcs() - 1) { t3ahelp.set(t3ahelp.get()+1); flag.wait(); } } catch (InterruptedException exn) { throwInternalError("thread was interrupted during a wait. i=" +i); } flag.set(); doWork(); flag.check("exited wait"); } doWork(); flag.check("outside sync"); synchronized (flag) { flag.check("inside second sync"); flag.notify(); doWork(); flag.check("inside second sync after notify"); } } //------------------------------------------------------------------------------------ // test timed wait/notify public static Flag t3bhelp; public static void test3b(int single iters) { for (int single i = 0; i < iters; i++) { if (Ti.thisProc() == 0) { System.out.print("."); System.out.flush(); } test3bsub(i); Ti.barrier(); } } private static void test3bsub(int i) { if (Ti.thisProc() == 0) t3bhelp.set(0); Ti.barrier(); synchronized (flag) { flag.set(); doWork(); flag.check("entered sync"); if (Ti.thisProc() == 0) { do { long starttime = System.currentTimeMillis(); try { flag.wait(500); } catch (InterruptedException exn) { throwInternalError("thread was interrupted during a timed wait. i=" +i); } long endtime = System.currentTimeMillis(); double waittime = (endtime - starttime) / 1000.0; if (waittime < 0.4) throwInternalError("timed wait came back too early: " + waittime + ". i=" +i); if (waittime > 5) throwInternalError("timed wait came back too late: " + waittime + ". i=" +i); } while (t3bhelp.get() < Ti.numProcs() - 1); // waste time until everyone waiting } else { try { t3bhelp.set(t3bhelp.get()+1); flag.wait(); } catch (InterruptedException exn) { throwInternalError("thread was interrupted during a wait. i=" +i); } } flag.set(); doWork(); flag.check("exited wait"); } doWork(); flag.check("outside sync"); synchronized (flag) { flag.check("inside second sync"); flag.notify(); doWork(); flag.check("inside second sync after notify"); } } //------------------------------------------------------------------------------------ public static void main(String single [] single args) { if (Ti.thisProc() == 0) System.out.println("Beginning synchronization tests (this could take awhile)."); if (Ti.numProcs() < 4 && Ti.thisProc() == 0) System.out.println("WARNING: Ti.numProcs() == " + Ti.numProcs() + ", too few for an accurate test!!"); int single iters = 30; Flag success = broadcast new Flag(1) from 0; flag = broadcast new Flag() from 0; t3ahelp = broadcast new Flag(0) from 0; t3bhelp = broadcast new Flag(0) from 0; if (false) { // test 1 has been moved to staticsync.ti success.set(1); Ti.barrier(); try { test1(iters); } catch (InternalError exn) { System.out.println("P#"+Ti.thisProc()+"/"+Ti.numProcs()+": Test1 FAILED: " + exn.getMessage()); success.set(0); } Ti.barrier(); if (Ti.thisProc() == 0) { if (success.get() != 0) System.out.println("Test1 PASSED."); else System.out.println("Test1 FAILED"); } Ti.barrier(); } success.set(1); synctest stobj = broadcast new synctest() from 0; Ti.barrier(); try { stobj.test1b(iters); } catch (InternalError exn) { System.out.println("P#"+Ti.thisProc()+"/"+Ti.numProcs()+": Test1b FAILED: " + exn.getMessage()); success.set(0); } Ti.barrier(); if (Ti.thisProc() == 0) { if (success.get() != 0) System.out.println("Test1b PASSED."); else System.out.println("Test1b FAILED"); } Ti.barrier(); success.set(1); Ti.barrier(); try { test2(iters); } catch (InternalError exn) { System.out.println("P#"+Ti.thisProc()+"/"+Ti.numProcs()+": Test2 FAILED: " + exn.getMessage()); success.set(0); } Ti.barrier(); if (Ti.thisProc() == 0) { if (success.get() != 0) System.out.println("Test2 PASSED."); else System.out.println("Test2 FAILED"); } Ti.barrier(); success.set(1); Ti.barrier(); try { test3a(iters); } catch (InternalError exn) { System.out.println("P#"+Ti.thisProc()+"/"+Ti.numProcs()+": Test3a FAILED: " + exn.getMessage()); success.set(0); } Ti.barrier(); if (Ti.thisProc() == 0) { if (success.get() != 0) System.out.println("Test3a PASSED."); else System.out.println("Test3a FAILED"); } Ti.barrier(); success.set(1); Ti.barrier(); try { test3b(iters); } catch (InternalError exn) { System.out.println("P#"+Ti.thisProc()+"/"+Ti.numProcs()+": Test3b FAILED: " + exn.getMessage()); success.set(0); } Ti.barrier(); if (Ti.thisProc() == 0) { if (success.get() != 0) System.out.println("Test3b PASSED."); else System.out.println("Test3b FAILED"); } Ti.barrier(); if (Ti.thisProc() == 0) System.out.println("Tests complete"); } //------------------------------------------------------------------------------------ private static double junk; private static java.util.Random rand = broadcast new java.util.Random() from 0; public static void doWork() { double x = 1.00001; int [] junkarr = new int[16535]; try { Thread.sleep((int)(Ti.thisProc()*10)); } catch (InterruptedException exn) { throwInternalError("thread was interrupted during a sleep in doWork"); } for (int i = 0; i < 100000; i++) { x = x * 0.99999 / 0.9999; } try { Thread.sleep(rand.nextDouble() > 0.95 ? 1000 : 0); // for platforms w/o usleep } catch (InterruptedException exn) { throwInternalError("thread was interrupted during a sleep in doWork"); } junk = x; Thread.yield(); } public static void throwInternalError(String s) { throw new InternalError(s); } }