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
-----------------------------------------------------------------
======================================================================
- relates to
-
JDK-4184579 jit incorrectly implements volatile variables.
- Closed