Commit 02398f9c authored by Ivo Anjo's avatar Ivo Anjo

Introduce new doTransactionally API, and port existing examples to use it

parent 008657a4
...@@ -405,47 +405,24 @@ JNIEXPORT void JNICALL Java_javartm_Transaction_abort__J(JNIEnv *env, jclass cls ...@@ -405,47 +405,24 @@ JNIEXPORT void JNICALL Java_javartm_Transaction_abort__J(JNIEnv *env, jclass cls
} }
} }
/*
JNIEXPORT jobject JNICALL Java_javartm_Transaction_doTransactionally(JNIEnv *env, jclass cls, jobject atomicBlock, jobject fallbackBlock) {
static jmethodID callMethodId = NULL;
if (callMethodId == NULL) {
jclass atomicBlockClass = (*env)->FindClass(env, "java/util/concurrent/Callable");
callMethodId = (*env)->GetMethodID(env, atomicBlockClass, "call", "()Ljava/lang/Object;");
if (!callMethodId) return NULL;
}
printf("Preparing execution...\n");
int res = _xbegin();
if (_xtest()) {
jobject retValue = (*env)->CallObjectMethod(env, atomicBlock, callMethodId);
_xend();
printf("Successful commit\n");
return retValue;
}
printf("Abort or failed to start tx res = %d\n", res);
return (*env)->CallObjectMethod(env, fallbackBlock, callMethodId);
}
*/
// How many times failed transactions inside doTransactionally are retried // How many times failed transactions inside doTransactionally are retried
// 10 was enough to hit at least 99.999% with most tests // 10 was enough to hit at least 99.999% with most tests
#define RETRIES 10 #define RETRIES 10
JNIEXPORT jboolean JNICALL Java_javartm_Transaction_doTransactionally(JNIEnv *env, jclass cls, jobject runnable, jboolean warmup) { JNIEXPORT jobject JNICALL Java_javartm_Transaction_doTransactionally(JNIEnv *env, jclass cls, jobject runnable, jboolean warmup) {
static jmethodID runMethodId = NULL; static jmethodID runMethodId = NULL;
if (runMethodId == NULL) { if (runMethodId == NULL) {
jclass atomicBlockClass = (*env)->FindClass(env, "java/lang/Runnable"); jclass atomicBlockClass = (*env)->FindClass(env, "javartm/AtomicRunnable");
runMethodId = (*env)->GetMethodID(env, atomicBlockClass, "run", "()V"); runMethodId = (*env)->GetMethodID(env, atomicBlockClass, "run", "()Ljava/lang/Object;");
if (!runMethodId) return 0; if (!runMethodId) return NULL;
} }
for (int i = 0; i < RETRIES; i++) { for (int i = 0; i < RETRIES; i++) {
if (warmup || (begin() == _XBEGIN_STARTED)) { if (warmup || (begin() == _XBEGIN_STARTED)) {
(*env)->CallVoidMethod(env, runnable, runMethodId); jobject retValue = (*env)->CallObjectMethod(env, runnable, runMethodId);
if (!warmup) _xend(); if (!warmup) _xend();
return 1; return retValue;
} }
} }
return 0; return NULL;
} }
/*
* javartm: a Java library for Restricted Transactional Memory
* Copyright (C) 2013 Ivo Anjo <ivo.anjo@ist.utl.pt>
*
* This file is part of javartm.
*
* javartm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* javartm 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with javartm. If not, see <http://www.gnu.org/licenses/>.
*/
package javartm;
/**
* An AtomicRunnable contains a block of code which will be executed transactionally, and methods that
* are before/after the warmup process.
*/
public abstract class AtomicRunnable<V> {
protected void beforeWarmup() { }
protected void afterWarmup() { }
public abstract V run();
}
...@@ -24,11 +24,13 @@ public final class Test3 { ...@@ -24,11 +24,13 @@ public final class Test3 {
public static int x, y; public static int x, y;
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
final Runnable transaction = new Runnable() { final AtomicRunnable<Void> transaction = new AtomicRunnable<Void>() {
public void run() { @Override
if (!Transaction.inTransaction()) return; public Void run() {
if (!Transaction.inTransaction()) return null;
x++; x++;
y++; y++;
return null;
} }
}; };
......
...@@ -28,8 +28,9 @@ public final class Test6 { ...@@ -28,8 +28,9 @@ public final class Test6 {
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
final int ITERS = 5000000; final int ITERS = 5000000;
final Runnable transaction = new Runnable() { final AtomicRunnable<Void> transaction = new AtomicRunnable<Void>() {
public void run() { @Override
public Void run() {
// The simpler warmup just returns with this test, but then the dummy method // The simpler warmup just returns with this test, but then the dummy method
// call will never work // call will never work
//if (!Transaction.inTransaction()) return; //if (!Transaction.inTransaction()) return;
...@@ -37,13 +38,17 @@ public final class Test6 { ...@@ -37,13 +38,17 @@ public final class Test6 {
y++; y++;
z++; z++;
dummy(); dummy();
return null;
}
@Override
public void afterWarmup() {
x = 0; y = 0; z = 0;
} }
}; };
Warmup.doWarmup(transaction); Warmup.doWarmup(transaction);
x = 0; y = 0; z = 0;
Thread[] threads = new Thread[Runtime.getRuntime().availableProcessors()]; Thread[] threads = new Thread[Runtime.getRuntime().availableProcessors()];
synchronized (Test6.class) { synchronized (Test6.class) {
......
...@@ -99,7 +99,8 @@ public final class Transaction { ...@@ -99,7 +99,8 @@ public final class Transaction {
// -XX:+PrintCompilation may be used to verify which methods are being recompiled. // -XX:+PrintCompilation may be used to verify which methods are being recompiled.
Log.trace("Warming up methods"); Log.trace("Warming up methods");
final Runnable dummyRunnable = new Runnable() { public void run() { } }; final AtomicRunnable<Void> dummyRunnable =
new AtomicRunnable<Void>() { @Override public Void run() { return null; } };
Warmup.doWarmup(new Runnable() { public void run() { Warmup.doWarmup(new Runnable() { public void run() {
inTransaction(); inTransaction();
...@@ -135,13 +136,11 @@ public final class Transaction { ...@@ -135,13 +136,11 @@ public final class Transaction {
**/ **/
public native static void abort(long reason); public native static void abort(long reason);
//public native static <V> V doTransactionally(Callable<V> atomicBlock, Callable<V> fallbackBlock); public static <V> V doTransactionally(AtomicRunnable<V> r) {
public static boolean doTransactionally(Runnable r) {
return doTransactionally(r, false); return doTransactionally(r, false);
} }
public native static boolean doTransactionally(Runnable r, boolean warmup); public native static <V> V doTransactionally(AtomicRunnable<V> r, boolean warmup);
public static short getAbortReason(int txStatus) { public static short getAbortReason(int txStatus) {
return (short) (txStatus >>> 24); return (short) (txStatus >>> 24);
......
...@@ -33,7 +33,7 @@ public class Warmup { ...@@ -33,7 +33,7 @@ public class Warmup {
// In some cases, the value above is not enough, so let's arbitrarily do a bit more // In some cases, the value above is not enough, so let's arbitrarily do a bit more
private static final int ITERATIONS = HOTSPOT_JIT_THRESHOLD * 3; private static final int ITERATIONS = HOTSPOT_JIT_THRESHOLD * 3;
/** Warmups up the received runnable by calling it repeatedly until the VM JIT kicks in **/ /** Warms up the received runnable by calling it repeatedly until the VM JIT kicks in **/
public static void doWarmup(Runnable r) { public static void doWarmup(Runnable r) {
for (int i = 0; i < ITERATIONS; i++) r.run(); for (int i = 0; i < ITERATIONS; i++) r.run();
try { try {
...@@ -41,4 +41,15 @@ public class Warmup { ...@@ -41,4 +41,15 @@ public class Warmup {
} catch (InterruptedException e) { throw new RuntimeException(e); } } catch (InterruptedException e) { throw new RuntimeException(e); }
Log.info("Warmup for " + r.getClass().getName() + " complete"); Log.info("Warmup for " + r.getClass().getName() + " complete");
} }
/** Warms up the received runnable by calling it repeatedly until the VM JIT kicks in **/
public static void doWarmup(AtomicRunnable<?> r) {
r.beforeWarmup();
for (int i = 0; i < ITERATIONS; i++) r.run();
r.afterWarmup();
try {
Thread.sleep(10);
} catch (InterruptedException e) { throw new RuntimeException(e); }
Log.info("Warmup for " + r.getClass().getName() + " complete");
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment