Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4023233

Memory accesses for doubles are not atomic.

XMLWordPrintable

    • generic, sparc
    • solaris_2.5.1, solaris_2.6


      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");
           }
         }
      }

            abuckley Alex Buckley
            ajacobssunw Allan Jacobs (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: