Skip to content

Commit

Permalink
[Truffle] Factor out releasing and acquiring the GIL.
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisseaton committed Sep 28, 2014
1 parent 70536db commit fb95f9a
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 130 deletions.
111 changes: 54 additions & 57 deletions core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Expand Up @@ -32,6 +32,7 @@
import org.jruby.truffle.runtime.core.RubyArray;
import org.jruby.truffle.runtime.core.RubyHash;
import org.jruby.truffle.runtime.subsystems.*;
import org.jruby.truffle.runtime.util.Supplier;

@CoreClass(name = "Kernel")
public abstract class KernelNodes {
Expand Down Expand Up @@ -390,17 +391,17 @@ public RubyString gets(VirtualFrame frame) {

final ThreadManager threadManager = context.getThreadManager();

String line;
final String line = getContext().outsideGlobalLock(new Supplier<String>() {

final RubyThread runningThread = threadManager.leaveGlobalLock();

try {
line = gets(context);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
threadManager.enterGlobalLock(runningThread);
}
@Override
public String get() {
try {
return gets(context);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});

final RubyString rubyLine = context.makeString(line);

Expand Down Expand Up @@ -559,20 +560,19 @@ public PNode(PNode prev) {
}

@Specialization
public NilPlaceholder p(VirtualFrame frame, Object[] args) {
public NilPlaceholder p(final VirtualFrame frame, final Object[] args) {
notDesignedForCompilation();

final ThreadManager threadManager = getContext().getThreadManager();

final RubyThread runningThread = threadManager.leaveGlobalLock();
getContext().outsideGlobalLock(new Runnable() {

try {
for (Object arg : args) {
getContext().getRuntime().getInstanceConfig().getOutput().println(inspect.call(frame, arg, "inspect", null));
@Override
public void run() {
for (Object arg : args) {
getContext().getRuntime().getInstanceConfig().getOutput().println(inspect.call(frame, arg, "inspect", null));
}
}
} finally {
threadManager.enterGlobalLock(runningThread);
}

});

return NilPlaceholder.INSTANCE;
}
Expand All @@ -594,22 +594,21 @@ public PrintNode(PrintNode prev) {
}

@Specialization
public NilPlaceholder print(VirtualFrame frame, Object[] args) {
final ThreadManager threadManager = getContext().getThreadManager();

final RubyThread runningThread = threadManager.leaveGlobalLock();
public NilPlaceholder print(final VirtualFrame frame, final Object[] args) {
getContext().outsideGlobalLock(new Runnable() {

try {
for (Object arg : args) {
try {
getContext().getRuntime().getInstanceConfig().getOutput().write(((RubyString) toS.call(frame, arg, "to_s", null)).getBytes().bytes());
} catch (IOException e) {
throw new RuntimeException(e);
@Override
public void run() {
for (Object arg : args) {
try {
getContext().getRuntime().getInstanceConfig().getOutput().write(((RubyString) toS.call(frame, arg, "to_s", null)).getBytes().bytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
} finally {
threadManager.enterGlobalLock(runningThread);
}

});

return NilPlaceholder.INSTANCE;
}
Expand All @@ -630,19 +629,18 @@ public PrintfNode(PrintfNode prev) {
public NilPlaceholder printf(Object[] args) {
notDesignedForCompilation();

final ThreadManager threadManager = getContext().getThreadManager();

if (args.length > 0) {
final String format = ((RubyString) args[0]).toString();
final String format = args[0].toString();
final List<Object> values = Arrays.asList(args).subList(1, args.length);

final RubyThread runningThread = threadManager.leaveGlobalLock();
getContext().outsideGlobalLock(new Runnable() {

try {
StringFormatter.format(getContext().getRuntime().getInstanceConfig().getOutput(), format, values);
} finally {
threadManager.enterGlobalLock(runningThread);
}
@Override
public void run() {
StringFormatter.format(getContext().getRuntime().getInstanceConfig().getOutput(), format, values);
}

});
}

return NilPlaceholder.INSTANCE;
Expand Down Expand Up @@ -867,28 +865,27 @@ public double sleep(double duration) {
}

@SlowPath
private double doSleep(double duration) {
private double doSleep(final double duration) {
notDesignedForCompilation();

final RubyContext context = getContext();
return getContext().outsideGlobalLock(new Supplier<Double>() {

final RubyThread runningThread = context.getThreadManager().leaveGlobalLock();
@Override
public Double get() {
final long start = System.nanoTime();

try {
final long start = System.nanoTime();
try {
Thread.sleep((long) (duration * 1000));
} catch (InterruptedException e) {
// Ignore interruption
}

try {
Thread.sleep((long) (duration * 1000));
} catch (InterruptedException e) {
// Ignore interruption
}
final long end = System.nanoTime();

final long end = System.nanoTime();
return (end - start) / 1e9;
}

return (end - start) / 1e9;
} finally {
context.getThreadManager().enterGlobalLock(runningThread);
}
});
}

@Specialization
Expand Down
Expand Up @@ -135,13 +135,14 @@ public NilPlaceholder garbageCollect() {
private NilPlaceholder doGC() {
notDesignedForCompilation();

final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();
getContext().outsideGlobalLock(new Runnable() {

try {
System.gc();
} finally {
getContext().getThreadManager().enterGlobalLock(runningThread);
}
@Override
public void run() {
System.gc();
}

});

return NilPlaceholder.INSTANCE;
}
Expand Down
9 changes: 9 additions & 0 deletions core/src/main/java/org/jruby/truffle/runtime/RubyContext.java
Expand Up @@ -38,6 +38,7 @@
import org.jruby.truffle.runtime.core.RubySymbol;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.subsystems.*;
import org.jruby.truffle.runtime.util.Supplier;
import org.jruby.truffle.translator.TranslatorDriver;
import org.jruby.util.ByteList;
import org.jruby.util.cli.Options;
Expand Down Expand Up @@ -299,6 +300,14 @@ public ThreadManager getThreadManager() {
return threadManager;
}

public void outsideGlobalLock(Runnable runnable) {
threadManager.outsideGlobalLock(runnable);
}

public <T> T outsideGlobalLock(Supplier<T> supplier) {
return threadManager.outsideGlobalLock(supplier);
}

public TranslatorDriver getTranslator() {
return translator;
}
Expand Down
23 changes: 12 additions & 11 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyThread.java
Expand Up @@ -103,20 +103,21 @@ public void shutdown() {
}

public void join() {
final RubyThread runningThread = getRubyClass().getContext().getThreadManager().leaveGlobalLock();
getRubyClass().getContext().outsideGlobalLock(new Runnable() {

try {
while (true) {
try {
finished.await();
break;
} catch (InterruptedException e) {
// Await again
@Override
public void run() {
while (true) {
try {
finished.await();
break;
} catch (InterruptedException e) {
// Await again
}
}
}
} finally {
runningThread.manager.enterGlobalLock(runningThread);
}

});

if (exception != null) {
throw new RaiseException(exception);
Expand Down

0 comments on commit fb95f9a

Please sign in to comment.