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

incorrect implementation of volatile variables on multiCPU WinNT

XMLWordPrintable

    • beta2
    • sparc
    • solaris_7



      Name: akC45999 Date: 12/09/99


      JCK13 test thrd02301 which implements Dekker's synchronization
      algorithm fails with HotSpot (jdk1.3.0Q) on 2 processor WinNT platform
      (lang/THRD/thrd023/thrd02301/thrd02301.html).
      Note, the test passes with Classic VM (jdk1.3.0Q) on the same platform.

      The test failed with jit (jdk1.2.*), see bug #4184579, closed
      as 'will not be fixed'.

      z:> java -version
      java version "1.3.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-Q)
      Java HotSpot(TM) Client VM (build 1.3-P, mixed mode)

      ------------- test source:

      import java.io.PrintStream;
      public class thrd02301 extends Thread {
        static final int timeout=30000;
        static final int actionLimit=1000000;
        static final int failureLimit=4;
        long endTime;
        PrintStream out;
        boolean threadNum;
        thrd02301 common, other;
        volatile boolean want=false, turn; // variables used in Dekker's algorithm
        volatile boolean locked=false; // true when this thread owns the lock
        volatile int counter // counts actions
                      , step // counter*4
                      , failures;
        volatile int termReason=0;

        thrd02301(boolean threadNum, PrintStream out, long endTime) {
              this.threadNum=threadNum;
              this.out=out;
              this.endTime=endTime;
        }

        void log(String message) {
              out.println("Thread "+(threadNum?"1: ":"0: ")+message);
        }

        void action() throws InterruptedException {
              want=true;
              step++; // step%4==1
              // lock phase of Dekker's algorithm
              int otherstep1=other.step, trycnt1=0;
              while (other.want) {
                      if (common.turn!=threadNum) {
                              want=false;
                              int trycnt2=0;
                              while (common.turn!=threadNum) {
                                      if ((++trycnt2)%500000==0) Thread.sleep(50);
                                      else if (trycnt2%50000==0) Thread.yield();
                              }
                              want=true;
                      } else if ((++trycnt1)%500000==0) Thread.sleep(50);
                      else if (trycnt1%50000==0) Thread.yield();
              }
              step++; // step%4==2
              locked=true;
              int otherstep2=other.step;
              // check that the other thread cannot gain the lock
              for (int k=0; k<10000; k++) {
                      if (other.locked) {
                              int otherstep3=other.step;
                              log("failure on counter "+counter+" k="+k);
                              log("step-1: "+(step-1)+"-->"+otherstep1);
                              log("step/a: "+step+"-->"+otherstep2);
                              log("step/b: "+step+"-->"+otherstep3);
                              failures++;
                              break;
                      }
              }

              locked=false;
              step++; /// step%4==3
              // unlock phase of Dekker's algorithm
              common.turn=other.threadNum;
              want=false;
              step++; /// step%4==0
        }

        public void run() {
              for (counter=0; counter<actionLimit; counter++) {
                      try {
                              action();
                      } catch (InterruptedException e) {
                              termReason=1;
                              return;
                      }
                      if (counter%10==0) {
                              if (System.currentTimeMillis()>=endTime) {
                                      termReason=2;
                                      return;
                              } else if (failures>failureLimit) {
                                      termReason=3;
                                      return;
                              } else if (other.termReason!=0) {
                                      termReason=4;
                                      return;
                              }
                      }
              }
        }

      //=========================
        public static int run(String args[], PrintStream out) {
              long curTime=System.currentTimeMillis();
              long endTime=curTime+timeout;
              thrd02301 thread0=new thrd02301(false, out, endTime)
                              , thread1=new thrd02301(true, out, endTime);
              thread0.common=thread1.common=thread0;
              thread0.other=thread1; thread1.other=thread0;
              thread0.start();
              thread1.start();
              try {
                      thread0.join();
                      thread1.join();
              } catch (InterruptedException e) {
                      out.println("InterruptedException in join()");
                      return 2/*STATUS_FAILED*/;
              }
              if ((thread0.termReason==1) || (thread1.termReason==1)) {
                      out.println("InterruptedException in child thread");
                      return 2/*STATUS_FAILED*/;
              }
              int failures=thread0.failures+thread1.failures;
              if (failures>0) {
                      out.println("failures:"+thread0.failures);
                      return 2/*STATUS_FAILED*/;
              }
              return 0/*STATUS_PASSED*/;
        }

        public static void main(String args[]) {
              System.exit(run(args, System.out) + 95/*STATUS_TEMP*/);
        }

      } // end class thrd02301

      ------------- test output:

      Thread 0: failure on counter 7795 k=18
      Thread 1: failure on counter 7698 k=0
      Thread 0: step-1: 31181-->30793
      Thread 1: step-1: 30793-->31178
      Thread 0: step/a: 31182-->30793
      Thread 1: step/a: 30794-->31182
      Thread 0: step/b: 31182-->30794
      Thread 1: step/b: 30794-->31182
      Thread 0: failure on counter 7899 k=16
      Thread 1: failure on counter 7774 k=0
      Thread 0: step-1: 31597-->31097
      Thread 1: step-1: 31097-->31594
      Thread 0: step/a: 31598-->31097
      Thread 1: step/a: 31098-->31598
      Thread 0: step/b: 31598-->31098
      Thread 1: step/b: 31098-->31598
      Thread 1: failure on counter 8357 k=0
      Thread 0: failure on counter 8733 k=11
      Thread 0: step-1: 34933-->33429
      Thread 0: step/a: 34934-->33429
      Thread 0: step/b: 34934-->33430
      Thread 1: step-1: 33429-->34930
      Thread 1: step/a: 33430-->34934
      Thread 1: step/b: 33430-->34934
      Thread 1: failure on counter 9040 k=0
      Thread 0: failure on counter 9706 k=16
      Thread 1: step-1: 36161-->38822
      Thread 0: step-1: 38825-->36161
      Thread 1: step/a: 36162-->38826
      Thread 0: step/a: 38826-->36161
      Thread 1: step/b: 36162-->38826
      Thread 0: step/b: 38826-->36162
      Thread 1: failure on counter 9113 k=0
      Thread 0: failure on counter 9797 k=18
      Thread 1: step-1: 36453-->39186
      Thread 0: step-1: 39189-->36453
      Thread 1: step/a: 36454-->39190
      Thread 0: step/a: 39190-->36453
      Thread 1: step/b: 36454-->39190
      Thread 0: step/b: 39190-->36454
      failures:5
      -----------------------------------------------------------------
       
      ======================================================================

            smitrovisunw Srdjan Mitrovic (Inactive)
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: