//  $Archive::                                                            $
//     $Date: Fri, 23 Feb 2001 18:00:52 -0800 $
// $Revision: 1.2 $
// Description: Titanium barrier tester
// Copyright 2000, Dan Bonachea <bonachea@cs.berkeley.edu>


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) {
    if (this.val != val) throw new InternalError("flag mismatch - illegal synchronization detected." +
                  "( val = " + val + ", flag = " + this.val + " )");
    }
  public void check() {
    check(Ti.thisProc());
    }
  }
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
public class barriertest {
  private static Flag flag;

  //------------------------------------------------------------------------------------
  // test barrier
  public static void test2(int single iters) {
    for (int single i=0 ; i < iters ; i++) {
      test2sub(i);
      }
    }
  private static void test2sub(int currflag) {
    flag.set(currflag);
    for (int i = 0; i < Ti.thisProc(); i++) {
      doWork();
      flag.check(currflag);
      }
    Ti.barrier();
    flag.set(-1);
    Ti.barrier();
    }


  //------------------------------------------------------------------------------------
  public static void main(String single [] single args) {
    if (Ti.thisProc() == 0) System.out.println("Beginning barrier test (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 = 100;
    Flag success = broadcast new Flag(1) from 0;
    flag = broadcast new Flag() from 0;

    Ti.barrier();
    try {
      test2(iters);
      }
    catch (InternalError exn) {
      System.out.println("P#"+Ti.thisProc()+"/"+Ti.numProcs()+": Barrier FAILED: " + exn.getMessage());
      success.set(0);
      }
    Ti.barrier();
    if (Ti.thisProc() == 0) {
      if (success.get() != 0) System.out.println("Barrier PASSED.");
      else System.out.println("Barrier FAILED");
      }
    Ti.barrier();


    if (Ti.thisProc() == 0) System.out.println("Barrier Test complete");
    }

  //------------------------------------------------------------------------------------
  private static double junk;
  private static int workctr = 0;

  public static void doWork() {
    double x = 1.00001;
    int [] junkarr = new int[16535]; 
    
    try {
      Thread.sleep(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 {
      workctr++;
      if (workctr % Ti.numProcs() == Ti.thisProc()) 
        Thread.sleep(1000);  // 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);
    }
 }