Merge
This commit is contained in:
commit
80b04bb48e
@ -279,7 +279,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ stmxcsr(mxcsr_save);
|
||||
__ movl(rax, mxcsr_save);
|
||||
__ andl(rax, MXCSR_MASK); // Only check control and mask bits
|
||||
ExternalAddress mxcsr_std(StubRoutines::x86::mxcsr_std());
|
||||
ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std());
|
||||
__ cmp32(rax, mxcsr_std);
|
||||
__ jcc(Assembler::equal, skip_ldmx);
|
||||
__ ldmxcsr(mxcsr_std);
|
||||
@ -729,17 +729,18 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
if (CheckJNICalls) {
|
||||
Label ok_ret;
|
||||
ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std());
|
||||
__ push(rax);
|
||||
__ subptr(rsp, wordSize); // allocate a temp location
|
||||
__ stmxcsr(mxcsr_save);
|
||||
__ movl(rax, mxcsr_save);
|
||||
__ andl(rax, MXCSR_MASK); // Only check control and mask bits
|
||||
__ cmpl(rax, *(int *)(StubRoutines::x86::mxcsr_std()));
|
||||
__ cmp32(rax, mxcsr_std);
|
||||
__ jcc(Assembler::equal, ok_ret);
|
||||
|
||||
__ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall");
|
||||
|
||||
__ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std()));
|
||||
__ ldmxcsr(mxcsr_std);
|
||||
|
||||
__ bind(ok_ret);
|
||||
__ addptr(rsp, wordSize);
|
||||
@ -3767,12 +3768,35 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return stub->entry_point();
|
||||
}
|
||||
|
||||
void create_control_words() {
|
||||
// Round to nearest, 53-bit mode, exceptions masked
|
||||
StubRoutines::_fpu_cntrl_wrd_std = 0x027F;
|
||||
// Round to zero, 53-bit mode, exception mased
|
||||
StubRoutines::_fpu_cntrl_wrd_trunc = 0x0D7F;
|
||||
// Round to nearest, 24-bit mode, exceptions masked
|
||||
StubRoutines::_fpu_cntrl_wrd_24 = 0x007F;
|
||||
// Round to nearest, 64-bit mode, exceptions masked
|
||||
StubRoutines::_fpu_cntrl_wrd_64 = 0x037F;
|
||||
// Round to nearest, 64-bit mode, exceptions masked
|
||||
StubRoutines::_mxcsr_std = 0x1F80;
|
||||
// Note: the following two constants are 80-bit values
|
||||
// layout is critical for correct loading by FPU.
|
||||
// Bias for strict fp multiply/divide
|
||||
StubRoutines::_fpu_subnormal_bias1[0]= 0x00000000; // 2^(-15360) == 0x03ff 8000 0000 0000 0000
|
||||
StubRoutines::_fpu_subnormal_bias1[1]= 0x80000000;
|
||||
StubRoutines::_fpu_subnormal_bias1[2]= 0x03ff;
|
||||
// Un-Bias for strict fp multiply/divide
|
||||
StubRoutines::_fpu_subnormal_bias2[0]= 0x00000000; // 2^(+15360) == 0x7bff 8000 0000 0000 0000
|
||||
StubRoutines::_fpu_subnormal_bias2[1]= 0x80000000;
|
||||
StubRoutines::_fpu_subnormal_bias2[2]= 0x7bff;
|
||||
}
|
||||
|
||||
// Initialization
|
||||
void generate_initial() {
|
||||
// Generates all stubs and initializes the entry points
|
||||
|
||||
// This platform-specific stub is needed by generate_call_stub()
|
||||
StubRoutines::x86::_mxcsr_std = generate_fp_mask("mxcsr_std", 0x0000000000001F80);
|
||||
// This platform-specific settings are needed by generate_call_stub()
|
||||
create_control_words();
|
||||
|
||||
// entry points that exist in all platforms Note: This is code
|
||||
// that could be shared among different platforms - however the
|
||||
|
@ -42,4 +42,3 @@ address StubRoutines::x86::_float_sign_mask = NULL;
|
||||
address StubRoutines::x86::_float_sign_flip = NULL;
|
||||
address StubRoutines::x86::_double_sign_mask = NULL;
|
||||
address StubRoutines::x86::_double_sign_flip = NULL;
|
||||
address StubRoutines::x86::_mxcsr_std = NULL;
|
||||
|
@ -52,7 +52,6 @@ class x86 {
|
||||
static address _float_sign_flip;
|
||||
static address _double_sign_mask;
|
||||
static address _double_sign_flip;
|
||||
static address _mxcsr_std;
|
||||
|
||||
public:
|
||||
|
||||
@ -106,11 +105,6 @@ class x86 {
|
||||
return _double_sign_flip;
|
||||
}
|
||||
|
||||
static address mxcsr_std()
|
||||
{
|
||||
return _mxcsr_std;
|
||||
}
|
||||
|
||||
# include "stubRoutines_x86.hpp"
|
||||
|
||||
};
|
||||
|
@ -138,6 +138,16 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true if all argument elements of vars are returned
|
||||
bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) {
|
||||
for (int i = 0; i < _arg_size; i++) {
|
||||
if (vars.contains(i) && !_arg_returned.test(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) {
|
||||
for (int i = 0; i < _arg_size; i++) {
|
||||
if (vars.contains(i)) {
|
||||
@ -166,6 +176,11 @@ void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars, bool merge) {
|
||||
if (vars.contains_unknown() || vars.contains_vars()) {
|
||||
_return_allocated = false;
|
||||
}
|
||||
if (_return_local && vars.contains_vars() && !returns_all(vars)) {
|
||||
// Return result should be invalidated if args in new
|
||||
// state are not recorded in return state.
|
||||
_return_local = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ class BCEscapeAnalyzer : public ResourceObj {
|
||||
void set_returned(ArgumentMap vars);
|
||||
bool is_argument(ArgumentMap vars);
|
||||
bool is_arg_stack(ArgumentMap vars);
|
||||
bool returns_all(ArgumentMap vars);
|
||||
void clear_bits(ArgumentMap vars, VectorSet &bs);
|
||||
void set_method_escape(ArgumentMap vars);
|
||||
void set_global_escape(ArgumentMap vars, bool merge = false);
|
||||
|
@ -2305,26 +2305,26 @@ void Matcher::validate_null_checks( ) {
|
||||
// atomic instruction acting as a store_load barrier without any
|
||||
// intervening volatile load, and thus we don't need a barrier here.
|
||||
// We retain the Node to act as a compiler ordering barrier.
|
||||
bool Matcher::post_store_load_barrier(const Node *vmb) {
|
||||
Compile *C = Compile::current();
|
||||
assert( vmb->is_MemBar(), "" );
|
||||
assert( vmb->Opcode() != Op_MemBarAcquire, "" );
|
||||
const MemBarNode *mem = (const MemBarNode*)vmb;
|
||||
bool Matcher::post_store_load_barrier(const Node* vmb) {
|
||||
Compile* C = Compile::current();
|
||||
assert(vmb->is_MemBar(), "");
|
||||
assert(vmb->Opcode() != Op_MemBarAcquire, "");
|
||||
const MemBarNode* membar = vmb->as_MemBar();
|
||||
|
||||
// Get the Proj node, ctrl, that can be used to iterate forward
|
||||
Node *ctrl = NULL;
|
||||
DUIterator_Fast imax, i = mem->fast_outs(imax);
|
||||
while( true ) {
|
||||
ctrl = mem->fast_out(i); // Throw out-of-bounds if proj not found
|
||||
assert( ctrl->is_Proj(), "only projections here" );
|
||||
ProjNode *proj = (ProjNode*)ctrl;
|
||||
if( proj->_con == TypeFunc::Control &&
|
||||
!C->node_arena()->contains(ctrl) ) // Unmatched old-space only
|
||||
// Get the Ideal Proj node, ctrl, that can be used to iterate forward
|
||||
Node* ctrl = NULL;
|
||||
for (DUIterator_Fast imax, i = membar->fast_outs(imax); i < imax; i++) {
|
||||
Node* p = membar->fast_out(i);
|
||||
assert(p->is_Proj(), "only projections here");
|
||||
if ((p->as_Proj()->_con == TypeFunc::Control) &&
|
||||
!C->node_arena()->contains(p)) { // Unmatched old-space only
|
||||
ctrl = p;
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
assert((ctrl != NULL), "missing control projection");
|
||||
|
||||
for( DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++ ) {
|
||||
for (DUIterator_Fast jmax, j = ctrl->fast_outs(jmax); j < jmax; j++) {
|
||||
Node *x = ctrl->fast_out(j);
|
||||
int xop = x->Opcode();
|
||||
|
||||
@ -2336,37 +2336,36 @@ bool Matcher::post_store_load_barrier(const Node *vmb) {
|
||||
// that a monitor exit operation contains a serializing instruction.
|
||||
|
||||
if (xop == Op_MemBarVolatile ||
|
||||
xop == Op_FastLock ||
|
||||
xop == Op_CompareAndSwapL ||
|
||||
xop == Op_CompareAndSwapP ||
|
||||
xop == Op_CompareAndSwapN ||
|
||||
xop == Op_CompareAndSwapI)
|
||||
xop == Op_CompareAndSwapI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Op_FastLock previously appeared in the Op_* list above.
|
||||
// With biased locking we're no longer guaranteed that a monitor
|
||||
// enter operation contains a serializing instruction.
|
||||
if ((xop == Op_FastLock) && !UseBiasedLocking) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (x->is_MemBar()) {
|
||||
// We must retain this membar if there is an upcoming volatile
|
||||
// load, which will be preceded by acquire membar.
|
||||
if (xop == Op_MemBarAcquire)
|
||||
// load, which will be followed by acquire membar.
|
||||
if (xop == Op_MemBarAcquire) {
|
||||
return false;
|
||||
// For other kinds of barriers, check by pretending we
|
||||
// are them, and seeing if we can be removed.
|
||||
else
|
||||
return post_store_load_barrier((const MemBarNode*)x);
|
||||
} else {
|
||||
// For other kinds of barriers, check by pretending we
|
||||
// are them, and seeing if we can be removed.
|
||||
return post_store_load_barrier(x->as_MemBar());
|
||||
}
|
||||
}
|
||||
|
||||
// Delicate code to detect case of an upcoming fastlock block
|
||||
if( x->is_If() && x->req() > 1 &&
|
||||
!C->node_arena()->contains(x) ) { // Unmatched old-space only
|
||||
Node *iff = x;
|
||||
Node *bol = iff->in(1);
|
||||
// The iff might be some random subclass of If or bol might be Con-Top
|
||||
if (!bol->is_Bool()) return false;
|
||||
assert( bol->req() > 1, "" );
|
||||
return (bol->in(1)->Opcode() == Op_FastUnlock);
|
||||
}
|
||||
// probably not necessary to check for these
|
||||
if (x->is_Call() || x->is_SafePoint() || x->is_block_proj())
|
||||
if (x->is_Call() || x->is_SafePoint() || x->is_block_proj()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -294,25 +294,7 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
|
||||
// If reference is volatile, prevent following volatiles ops from
|
||||
// floating up before the volatile write.
|
||||
if (is_vol) {
|
||||
// First place the specific membar for THIS volatile index. This first
|
||||
// membar is dependent on the store, keeping any other membars generated
|
||||
// below from floating up past the store.
|
||||
int adr_idx = C->get_alias_index(adr_type);
|
||||
insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx, store);
|
||||
|
||||
// Now place a membar for AliasIdxBot for the unknown yet-to-be-parsed
|
||||
// volatile alias indices. Skip this if the membar is redundant.
|
||||
if (adr_idx != Compile::AliasIdxBot) {
|
||||
insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot, store);
|
||||
}
|
||||
|
||||
// Finally, place alias-index-specific membars for each volatile index
|
||||
// that isn't the adr_idx membar. Typically there's only 1 or 2.
|
||||
for( int i = Compile::AliasIdxRaw; i < C->num_alias_types(); i++ ) {
|
||||
if (i != adr_idx && C->alias_type(i)->is_volatile()) {
|
||||
insert_mem_bar_volatile(Op_MemBarVolatile, i, store);
|
||||
}
|
||||
}
|
||||
insert_mem_bar(Op_MemBarVolatile); // Use fat membar
|
||||
}
|
||||
|
||||
// If the field is final, the rules of Java say we are in <init> or <clinit>.
|
||||
|
82
hotspot/test/compiler/EscapeAnalysis/Test8020215.java
Normal file
82
hotspot/test/compiler/EscapeAnalysis/Test8020215.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8020215
|
||||
* @summary Different execution plan when using JIT vs interpreter
|
||||
* @run main Test8020215
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Test8020215 {
|
||||
public static class NamedObject {
|
||||
public int id;
|
||||
public String name;
|
||||
public NamedObject(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NamedObjectList {
|
||||
public List<NamedObject> namedObjectList = new ArrayList<NamedObject>();
|
||||
|
||||
public NamedObject getBest(int id) {
|
||||
NamedObject bestObject = null;
|
||||
for (NamedObject o : namedObjectList) {
|
||||
bestObject = id==o.id ? getBetter(bestObject, o) : bestObject;
|
||||
}
|
||||
return (bestObject != null) ? bestObject : null;
|
||||
}
|
||||
|
||||
private static NamedObject getBetter(NamedObject p1, NamedObject p2) {
|
||||
return (p1 == null) ? p2 : (p2 == null) ? p1 : (p2.name.compareTo(p1.name) >= 0) ? p2 : p1;
|
||||
}
|
||||
}
|
||||
|
||||
static void test(NamedObjectList b, int i) {
|
||||
NamedObject x = b.getBest(2);
|
||||
// test
|
||||
if (x == null) {
|
||||
throw new RuntimeException("x should never be null here! (i=" + i + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// setup
|
||||
NamedObjectList b = new NamedObjectList();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
b.namedObjectList.add(new NamedObject(1, "2012-12-31"));
|
||||
}
|
||||
b.namedObjectList.add(new NamedObject(2, "2013-12-31"));
|
||||
|
||||
// execution
|
||||
for (int i = 0; i < 12000; i++) {
|
||||
test(b, i);
|
||||
}
|
||||
System.out.println("PASSED");
|
||||
}
|
||||
}
|
42
hotspot/test/compiler/cpuflags/RestoreMXCSR.java
Normal file
42
hotspot/test/compiler/cpuflags/RestoreMXCSR.java
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8020433
|
||||
* @summary Crash when using -XX:+RestoreMXCSROnJNICalls
|
||||
* @library /testlibrary
|
||||
*
|
||||
*/
|
||||
import com.oracle.java.testlibrary.*;
|
||||
|
||||
public class RestoreMXCSR {
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProcessBuilder pb;
|
||||
OutputAnalyzer out;
|
||||
|
||||
pb = ProcessTools.createJavaProcessBuilder("-XX:+RestoreMXCSROnJNICalls", "-version");
|
||||
out = new OutputAnalyzer(pb.start());
|
||||
out.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
163
hotspot/test/compiler/membars/DekkerTest.java
Normal file
163
hotspot/test/compiler/membars/DekkerTest.java
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2013 SAP AG. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8007898
|
||||
* @summary Incorrect optimization of Memory Barriers in Matcher::post_store_load_barrier().
|
||||
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
|
||||
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
|
||||
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CICompilerCount=1 -XX:+StressGCM -XX:+StressLCM DekkerTest
|
||||
* @author Martin Doerr martin DOT doerr AT sap DOT com
|
||||
*
|
||||
* Run 3 times since the failure is intermittent.
|
||||
*/
|
||||
|
||||
public class DekkerTest {
|
||||
|
||||
/*
|
||||
Read After Write Test (basically a simple Dekker test with volatile variables)
|
||||
Derived from the original jcstress test, available at:
|
||||
http://hg.openjdk.java.net/code-tools/jcstress/file/6c339a5aa00d/
|
||||
tests-custom/src/main/java/org/openjdk/jcstress/tests/volatiles/DekkerTest.java
|
||||
*/
|
||||
|
||||
static final int ITERATIONS = 1000000;
|
||||
|
||||
static class TestData {
|
||||
public volatile int a;
|
||||
public volatile int b;
|
||||
}
|
||||
|
||||
static class ResultData {
|
||||
public int a;
|
||||
public int b;
|
||||
}
|
||||
|
||||
TestData[] testDataArray;
|
||||
ResultData[] results;
|
||||
|
||||
volatile boolean start;
|
||||
|
||||
public DekkerTest() {
|
||||
testDataArray = new TestData[ITERATIONS];
|
||||
results = new ResultData[ITERATIONS];
|
||||
for (int i = 0; i < ITERATIONS; ++i) {
|
||||
testDataArray[i] = new TestData();
|
||||
results[i] = new ResultData();
|
||||
}
|
||||
start = false;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
for (int i = 0; i < ITERATIONS; ++i) {
|
||||
testDataArray[i].a = 0;
|
||||
testDataArray[i].b = 0;
|
||||
results[i].a = 0;
|
||||
results[i].b = 0;
|
||||
}
|
||||
start = false;
|
||||
}
|
||||
|
||||
int actor1(TestData t) {
|
||||
t.a = 1;
|
||||
return t.b;
|
||||
}
|
||||
|
||||
int actor2(TestData t) {
|
||||
t.b = 1;
|
||||
return t.a;
|
||||
}
|
||||
|
||||
class Runner1 extends Thread {
|
||||
public void run() {
|
||||
do {} while (!start);
|
||||
for (int i = 0; i < ITERATIONS; ++i) {
|
||||
results[i].a = actor1(testDataArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Runner2 extends Thread {
|
||||
public void run() {
|
||||
do {} while (!start);
|
||||
for (int i = 0; i < ITERATIONS; ++i) {
|
||||
results[i].b = actor2(testDataArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testRunner() {
|
||||
Thread thread1 = new Runner1();
|
||||
Thread thread2 = new Runner2();
|
||||
thread1.start();
|
||||
thread2.start();
|
||||
do {} while (!thread1.isAlive());
|
||||
do {} while (!thread2.isAlive());
|
||||
start = true;
|
||||
Thread.yield();
|
||||
try {
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("interrupted!");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
boolean printResult() {
|
||||
int[] count = new int[4];
|
||||
for (int i = 0; i < ITERATIONS; ++i) {
|
||||
int event_kind = (results[i].a << 1) + results[i].b;
|
||||
++count[event_kind];
|
||||
}
|
||||
if (count[0] == 0 && count[3] == 0) {
|
||||
System.out.println("[not interesting]");
|
||||
return false; // not interesting
|
||||
}
|
||||
String error = (count[0] == 0) ? " ok" : " disallowed!";
|
||||
System.out.println("[0,0] " + count[0] + error);
|
||||
System.out.println("[0,1] " + count[1]);
|
||||
System.out.println("[1,0] " + count[2]);
|
||||
System.out.println("[1,1] " + count[3]);
|
||||
return (count[0] != 0);
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
DekkerTest test = new DekkerTest();
|
||||
final int runs = 30;
|
||||
int failed = 0;
|
||||
for (int c = 0; c < runs; ++c) {
|
||||
test.testRunner();
|
||||
if (test.printResult()) {
|
||||
failed++;
|
||||
}
|
||||
test.reset();
|
||||
}
|
||||
if (failed > 0) {
|
||||
throw new InternalError("FAILED. Got " + failed + " failed ITERATIONS");
|
||||
}
|
||||
System.out.println("PASSED.");
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user