Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: fcbe0cf76a7a
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b08a9a35a724
Choose a head ref
  • 4 commits
  • 8 files changed
  • 1 contributor

Commits on Jan 15, 2015

  1. [Truffle] Run GC outside the global lock.

    * JVM's GCs are thread-safe and we run finalizers later.
    eregon committed Jan 15, 2015
    Copy the full SHA
    f159cec View commit details
  2. Copy the full SHA
    6cf70b2 View commit details
  3. Copy the full SHA
    43328c1 View commit details
  4. [Truffle] Interrupt all threads when using SafepointManager.pauseAllT…

    …hreads*.
    
    * So we can get out of Kernel#sleep for instance.
    * This might not be the wisest solution for sleep(),
      but it definitely is necessary if we use long-running
      system calls as they do not have any safepoint.
    * TODO: Review all InterruptedException catch blocks.
    eregon committed Jan 15, 2015
    Copy the full SHA
    b08a9a3 View commit details
18 changes: 9 additions & 9 deletions core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -1968,23 +1968,23 @@ public double sleep(double duration) {

@TruffleBoundary
private double doSleep(final double duration) {
final long start = System.nanoTime();

final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

try {
final long start = System.nanoTime();

try {
Thread.sleep((long) (duration * 1000));
} catch (InterruptedException e) {
// Ignore interruption
} finally {
getContext().getThreadManager().enterGlobalLock(runningThread);
}
} catch (InterruptedException e) {
getContext().getSafepointManager().poll();
}

final long end = System.nanoTime();
final long end = System.nanoTime();

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

}
Original file line number Diff line number Diff line change
@@ -12,9 +12,11 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyNilClass;
import org.jruby.truffle.runtime.core.RubyString;
import org.jruby.truffle.runtime.core.RubyThread;
import org.jruby.util.StringSupport;

/**
@@ -35,7 +37,14 @@ public VMGCStartPrimitiveNode(VMGCStartPrimitiveNode prev) {

@Specialization
public RubyNilClass vmGCStart() {
System.gc();
final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

try {
System.gc();
} finally {
getContext().getThreadManager().enterGlobalLock(runningThread);
}

return getContext().getCoreLibrary().getNilObject();
}

Original file line number Diff line number Diff line change
@@ -200,6 +200,12 @@ public void initialize() {
standardErrorClass = new RubyClass(context, objectClass, exceptionClass, "StandardError");
standardErrorClass.setAllocator(new RubyException.ExceptionAllocator());

RubyClass signalExceptionClass = new RubyClass(context, objectClass, exceptionClass, "SignalException");
signalExceptionClass.setAllocator(new RubyException.ExceptionAllocator());

RubyClass interruptClass = new RubyClass(context, objectClass, signalExceptionClass, "Interrupt");
interruptClass.setAllocator(new RubyException.ExceptionAllocator());

ioClass = new RubyClass(context, objectClass, objectClass, "IO");

argumentErrorClass = new RubyClass(context, objectClass, standardErrorClass, "ArgumentError");
14 changes: 14 additions & 0 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyThread.java
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ public void shutdown() {

private final CountDownLatch finished = new CountDownLatch(1);

private volatile Thread thread;
private Status status = Status.RUN;

private RubyException exception;
@@ -76,6 +77,7 @@ public void initialize(final RubyContext context, final RubyNode currentNode, Ru

@Override
public void run() {
thread = Thread.currentThread();
finalThread.manager.registerThread(finalThread);
finalThread.manager.enterGlobalLock(finalThread);
context.getSafepointManager().enterThread();
@@ -94,12 +96,17 @@ public void run() {
finalThread.finished.countDown();
context.getSafepointManager().leaveThread();
status = Status.DEAD;
thread = null;
}
}

}).start();
}

public void setRootThread(Thread thread) {
this.thread = thread;
}

public void join() {
final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

@@ -121,6 +128,13 @@ public void join() {
}
}

public void interrupt() {
Thread t = thread;
if (t != null) {
t.interrupt();
}
}

public Status getStatus() {
return status;
}
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@
/**
* Supports the Ruby {@code ObjectSpace} module. Object IDs are lazily allocated {@code long}
* values, mapped to objects with a weak hash map. Finalizers are implemented with weak references
* and reference queues, and are run in a dedicated Ruby thread (but not a dedicated Java thread).
* and reference queues, and are run in a dedicated Ruby thread.
*/
public class ObjectSpaceManager {

Original file line number Diff line number Diff line change
@@ -77,6 +77,8 @@ public synchronized void pauseAllThreadsAndExecute(final Consumer<RubyThread> ac

assumption.invalidate();

context.getThreadManager().interruptAllThreads();

// wait for all threads to reach their safepoint
waitOnBarrier();

@@ -101,6 +103,8 @@ public synchronized void pauseAllThreadsAndExecuteSignalHandler(final Consumer<R

assumption.invalidate();

context.getThreadManager().interruptAllThreads();

// wait for all threads to reach their safepoint
waitOnBarrierNoGlobalLock();

Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
package org.jruby.truffle.runtime.subsystems;

import com.oracle.truffle.api.CompilerDirectives;

import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyThread;

@@ -32,6 +33,7 @@ public class ThreadManager {

public ThreadManager(RubyContext context) {
rootThread = new RubyThread(context.getCoreLibrary().getThreadClass(), this);
rootThread.setRootThread(Thread.currentThread());
runningThreads.add(rootThread);
enterGlobalLock(rootThread);
}
@@ -73,6 +75,12 @@ public RubyThread getCurrentThread() {
return currentThread;
}

public void interruptAllThreads() {
for (RubyThread thread : runningThreads) {
thread.interrupt();
}
}

public synchronized void registerThread(RubyThread thread) {
runningThreads.add(thread);
}
5 changes: 5 additions & 0 deletions core/src/main/ruby/jruby/truffle/core/main.rb
Original file line number Diff line number Diff line change
@@ -6,6 +6,11 @@
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

Signal.trap("INT") do
raise Interrupt
end


module STDIN
def self.external_encoding
@external || Encoding.default_external