allan.jacobs@Eng 1996-12-20
The problem is present in the native thread implementation of the VM.  When
run with THREADS_FLAG not present in the environment, no printout appears
when the class is interpreted.  When THREADS_FLAG is set to native, the
error message "corruptedMemory" is written to standard output.
tarantula% unsetenv THREADS_FLAG
tarantula% javac -d . e1720101.java
tarantula% java X
tarantula% setenv THREADS_FLAG native
tarantula% java X
corruptedMemory
tarantula% cat e1720101.java
/**
 **   JAVATEST : The Modena JAVA Test Suite, Version 2.0, November 1996
 **   Copyright (c) 1996 Modena Software (I) Pvt. Ltd., All Rights Reserved
 **/
/*
 *  Section:  17.2
 *
 *  Filename: c1720101.java
 *
 *  Purpose:  Positive test for section 17.2, para 1:
 *
 *           "The actions performed by the main memory for any one variable
 *            are totally ordered; that is, for any two actions performed
 *            by the main memory on the same variable, one action precedes
 *            the other."
 *
 *           Section 17.4 para 2:
 *           "This matters because a read or write of a double or long 
 *            variable may be handled by an actual main memory as two
 *            32-bit read or write actions that may be separated in time,
 *            with other actions coming between them."
 *
 *
 *  Language Specification:  October, 1996
 */
//
// Note: When run on JDK1_0_2 for NT4.0/Win95, this test randomly fails runtime
//       execution. It is advisable that this test is manually run multiple
//       times to ensure the results.
//
//
// Test Description: Several threads simultaneously read/write on the
//                   same variable for lakhs of times. Variable should
//                   not have any other value except from the union of
//                   various predetermined values written by all the threads.
//
// Treats volatile double
//
class T1 extends Thread {
  final static double d1=Double.MAX_VALUE;
  public void run()
  {
    for(int i=0;i<500000;i++)
     {
       double dTemp=X.d;
       if((dTemp!=T1.d1)&&(dTemp!=T2.d2)&&(dTemp!=T3.d3)&&(dTemp!=T4.d4)&&(dTemp!=T5.d5))
        {
        //
        // stop all the threads, since X.d has unexpected value
        //
          X.corruptedMemory=true;
          X.t2.stop();
          X.t3.stop();
          X.t4.stop();
          X.t5.stop();
        }
       else
         X.d=d1;
     }
  }
}
class T2 extends Thread {
  final static double d2=Double.MIN_VALUE;
  public void run()
  {
    for(int i=0;i<500000;i++)
     {
       double dTemp=X.d;
       if((dTemp!=T1.d1)&&(dTemp!=T2.d2)&&(dTemp!=T3.d3)&&(dTemp!=T4.d4)&&(dTemp!=T5.d5))
        {
        //
        // stop all the threads, since X.d has unexpected value
        //
          X.corruptedMemory=true;
          X.t1.stop();
          X.t3.stop();
          X.t4.stop();
          X.t5.stop();
        }
       else
         X.d=d2;
     }
  }
}
class T3 extends Thread {
  final static double d3=0.0;
  public void run()
  {
    for(int i=0;i<500000;i++)
     {
       double dTemp=X.d;
       if((dTemp!=T1.d1)&&(dTemp!=T2.d2)&&(dTemp!=T3.d3)&&(dTemp!=T4.d4)&&(dTemp!=T5.d5))
        {
        //
        // stop all the threads, since X.d has unexpected value
        //
          X.corruptedMemory=true;
          X.t1.stop();
          X.t2.stop();
          X.t4.stop();
          X.t5.stop();
        }
       else
         X.d=d3;
     }
  }
}
class T4 extends Thread {
  final static double d4=999999;
  public void run()
  {
    for(int i=0;i<500000;i++)
     {
       double dTemp=X.d;
       if((dTemp!=T1.d1)&&(dTemp!=T2.d2)&&(dTemp!=T3.d3)&&(dTemp!=T4.d4)&&(dTemp!=T5.d5))
        {
        //
        // stop all the threads, since X.d has unexpected value
        //
          X.corruptedMemory=true;
          X.t1.stop();
          X.t2.stop();
          X.t3.stop();
          X.t5.stop();
        }
       else 
         X.d=d4;
     }
  }
}
class T5 extends Thread {
  final static double d5=-777777;
  public void run()
  {
    for(int i=0;i<500000;i++)
     {
       double dTemp=X.d;
       if((dTemp!=T1.d1)&&(dTemp!=T2.d2)&&(dTemp!=T3.d3)&&(dTemp!=T4.d4)&&(dTemp!=T5.d5))
        {
        //
        // stop all the threads, since X.d has unexpected value
        //
          X.corruptedMemory=true;
          X.t1.stop();
          X.t2.stop();
          X.t3.stop();
          X.t4.stop();
        }
       else 
         X.d=d5;
     }
  }
}
class X 
{
  static boolean corruptedMemory=false;
  static Thread t1=new T1();
  static Thread t2=new T2();
  static Thread t3=new T3();
  static Thread t4=new T4();
  static Thread t5=new T5();
  static volatile double d=T1.d1;
  public static void main(String argv[]) throws InterruptedException
   {
     try {
       t1.start();
       t2.start();
       t3.start();
       t4.start();
       t5.start();
       t1.join();
       t2.join();
       t3.join();
       t4.join();
       t5.join();
     }
     catch(Throwable e) { 
       corruptedMemory=true;
       System.err.println(e); // something very wrong 
     }
     if (corruptedMemory) {
        System.out.println("corruptedMemory");
     }
   }
}