/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2009, 2010 Peter Hilber (peter@hilber.name)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package rttm.tests.manual;
import static com.jopdesign.sys.Const.*;
import com.jopdesign.sys.Native;
import com.jopdesign.sys.RetryException;
import rttm.AbortException;
import rttm.Commands;
import rttm.internal.Utils;
/**
* This class serves both as a conceptual reference of an atomic method and
* as the base for the generation of an atomic method in
* com.jopdesign.build.ReplaceAtomicAnnotation
* (using org.apache.bcel.util.BCELifier to reverse engineer the compiled
* class).
*
* @author Peter Hilber (peter@hilber.name)
*/
public class Transaction {
public static boolean conflicting = false;
protected static int originalMethodBody(int arg0) throws RetryException,
AbortException, Throwable {
boolean ignored = conflicting;
return arg0;
}
/**
* @exception RetryException Thrown by hardware if a conflict is
* detected or by user program using {@link Commands#retry()} .
* Is not user-visible, i.e. not propagated outside of not nested
* transaction.
*
* @exception AbortExcepton Thrown by user program to abort transaction,
* using {@link Commands#abort()}.
* Is user-visible, i.e. propagated outside of not nested transaction.
*/
public static int atomicMethod(int arg0) throws RetryException,
AbortException, Throwable {
int arg0Copy = 0xdeadbeef; // make compiler happy
boolean isNotNestedTransaction =
!Utils.inTransaction[Native.rdMem(IO_CPU_ID)];
if (isNotNestedTransaction) {
arg0Copy = arg0; // save method arguments
Native.wrMem(0, IO_INT_ENA); // disable interrupts
Utils.inTransaction[Native.rdMem(IO_CPU_ID)] = true;
}
while (true) {
if (isNotNestedTransaction) {
Native.wrMem(TM_START_TRANSACTION, MEM_TM_MAGIC);
}
try {
// Not really a method invocation
// The original method body is inserted here, return
// statements in it are redirected to the next statement
int result = originalMethodBody(arg0);
if (isNotNestedTransaction) {
// try commit
Native.wrMem(TM_END_TRANSACTION, MEM_TM_MAGIC);
// no exceptions happen after here
Utils.inTransaction[Native.rdMem(IO_CPU_ID)] = false;
Native.wrMem(1, IO_INT_ENA); // re-enable interrupts
}
return result;
} catch (Throwable e) {
// exception handling issues ABORTED HW command
// e is RetryException, AbortException or other exception
if (isNotNestedTransaction) {
// reference comparison is enough for singleton
if (e == RetryException.instance) {
// restore method arguments
arg0 = arg0Copy;
} else {
// transaction was manually aborted or a bug triggered
Utils.inTransaction[Native.rdMem(IO_CPU_ID)] = false;
Native.wrMem(1, IO_INT_ENA); // re-enable interrupts
throw e;
}
} else { // nested transaction: propagate exception
throw e;
}
}
}
}
}