-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Truffle] Move ConditionVariable to Java for more control.
* Particularly, Thread.handle_interrupt(:never) with a blocking Mutex#lock is problematic.
- 9.4.12.0
- 9.4.11.0
- 9.4.10.0
- 9.4.9.0
- 9.4.8.0
- 9.4.7.0
- 9.4.6.0
- 9.4.5.0
- 9.4.4.0
- 9.4.3.0
- 9.4.2.0
- 9.4.1.0
- 9.4.0.0
- 9.3.15.0
- 9.3.14.0
- 9.3.13.0
- 9.3.12.0
- 9.3.11.0
- 9.3.10.0
- 9.3.9.0
- 9.3.8.0
- 9.3.7.0
- 9.3.6.0
- 9.3.5.0
- 9.3.4.0
- 9.3.3.0
- 9.3.2.0
- 9.3.1.0
- 9.3.0.0
- 9.2.21.0
- 9.2.20.1
- 9.2.20.0
- 9.2.19.0
- 9.2.18.0
- 9.2.17.0
- 9.2.16.0
- 9.2.15.0
- 9.2.14.0
- 9.2.13.0
- 9.2.12.0
- 9.2.11.1
- 9.2.11.0
- 9.2.10.0
- 9.2.9.0
- 9.2.8.0
- 9.2.7.0
- 9.2.6.0
- 9.2.5.0
- 9.2.4.1
- 9.2.4.0
- 9.2.3.0
- 9.2.2.0
- 9.2.1.0
- 9.2.0.0
- 9.1.17.0
- 9.1.16.0
- 9.1.15.0
- 9.1.14.0
- 9.1.13.0
- 9.1.12.0
- 9.1.11.0
- 9.1.10.0
- 9.1.9.0
- 9.1.8.0
- 9.1.7.0
- 9.1.6.0
- 9.1.5.0
- 9.1.4.0
- 9.1.3.0
Showing
11 changed files
with
289 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
exclude :test_condvar_wait_deadlock_2, "timeout" | ||
exclude :test_condvar_wait_and_broadcast, "timeout" | ||
exclude :test_condvar_wait_deadlock, "spawn" | ||
exclude :test_dup, "needs investigation" | ||
exclude :test_dump, "Binding#eval" | ||
exclude :test_dump, "copy of class methods of a class" | ||
exclude :"test_initialized", "needs investigation" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
truffle/src/main/java/org/jruby/truffle/core/cast/DurationToMillisecondsNode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This | ||
* code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
* redistribute it and/or modify it under the terms of the: | ||
* | ||
* Eclipse Public License version 1.0 | ||
* GNU General Public License version 2 | ||
* GNU Lesser General Public License version 2.1 | ||
*/ | ||
package org.jruby.truffle.core.cast; | ||
|
||
import com.oracle.truffle.api.CompilerDirectives; | ||
import com.oracle.truffle.api.dsl.NodeChild; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.frame.VirtualFrame; | ||
import com.oracle.truffle.api.object.DynamicObject; | ||
import com.oracle.truffle.api.profiles.ConditionProfile; | ||
import org.jruby.truffle.language.NotProvided; | ||
import org.jruby.truffle.language.RubyNode; | ||
import org.jruby.truffle.language.control.RaiseException; | ||
|
||
@NodeChild("duration") | ||
public abstract class DurationToMillisecondsNode extends RubyNode { | ||
|
||
@Child NumericToFloatNode floatCastNode; | ||
|
||
private final ConditionProfile durationLessThanZeroProfile = ConditionProfile.createBinaryProfile(); | ||
|
||
public abstract long executeDurationToMillis(VirtualFrame frame, Object duration); | ||
|
||
@Specialization | ||
public long duration(NotProvided duration) { | ||
return Long.MAX_VALUE; | ||
} | ||
|
||
@Specialization | ||
public long duration(int duration) { | ||
return validate(duration * 1000L); | ||
} | ||
|
||
@Specialization | ||
public long duration(long duration) { | ||
return validate(duration * 1000); | ||
} | ||
|
||
@Specialization | ||
public long duration(double duration) { | ||
return validate((long) (duration * 1000)); | ||
} | ||
|
||
@Specialization(guards = "isRubiniusUndefined(duration)") | ||
public long duration(DynamicObject duration) { | ||
return duration(NotProvided.INSTANCE); | ||
} | ||
|
||
@Specialization(guards = "!isRubiniusUndefined(duration)") | ||
public long duration(VirtualFrame frame, DynamicObject duration) { | ||
if (floatCastNode == null) { | ||
CompilerDirectives.transferToInterpreter(); | ||
floatCastNode = insert(NumericToFloatNodeGen.create(getContext(), getSourceSection(), "to_f", null)); | ||
} | ||
return duration(floatCastNode.executeDouble(frame, duration)); | ||
} | ||
|
||
private long validate(long durationInMillis) { | ||
if (durationLessThanZeroProfile.profile(durationInMillis < 0)) { | ||
throw new RaiseException(coreExceptions().argumentErrorTimeItervalPositive(this)); | ||
} | ||
return durationInMillis; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
truffle/src/main/java/org/jruby/truffle/core/mutex/ConditionVariableLayout.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. This | ||
* code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
* redistribute it and/or modify it under the terms of the: | ||
* | ||
* Eclipse Public License version 1.0 | ||
* GNU General Public License version 2 | ||
* GNU Lesser General Public License version 2.1 | ||
*/ | ||
package org.jruby.truffle.core.mutex; | ||
|
||
import com.oracle.truffle.api.object.DynamicObject; | ||
import com.oracle.truffle.api.object.DynamicObjectFactory; | ||
import com.oracle.truffle.api.object.dsl.Layout; | ||
import org.jruby.truffle.core.basicobject.BasicObjectLayout; | ||
|
||
@Layout | ||
public interface ConditionVariableLayout extends BasicObjectLayout { | ||
|
||
DynamicObjectFactory createConditionVariableShape( | ||
DynamicObject logicalClass, | ||
DynamicObject metaClass); | ||
|
||
DynamicObject createConditionVariable( | ||
DynamicObjectFactory factory, | ||
Object condition); | ||
|
||
boolean isConditionVariable(DynamicObject object); | ||
|
||
Object getCondition(DynamicObject object); | ||
|
||
} |
149 changes: 149 additions & 0 deletions
149
truffle/src/main/java/org/jruby/truffle/core/mutex/ConditionVariableNodes.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
/* | ||
* Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. This | ||
* code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
* redistribute it and/or modify it under the terms of the: | ||
* | ||
* Eclipse Public License version 1.0 | ||
* GNU General Public License version 2 | ||
* GNU Lesser General Public License version 2.1 | ||
*/ | ||
package org.jruby.truffle.core.mutex; | ||
|
||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; | ||
import com.oracle.truffle.api.dsl.CreateCast; | ||
import com.oracle.truffle.api.dsl.NodeChild; | ||
import com.oracle.truffle.api.dsl.NodeChildren; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.object.DynamicObject; | ||
import com.oracle.truffle.api.source.SourceSection; | ||
import java.util.concurrent.locks.ReentrantLock; | ||
import org.jruby.truffle.Layouts; | ||
import org.jruby.truffle.RubyContext; | ||
import org.jruby.truffle.builtins.CoreClass; | ||
import org.jruby.truffle.builtins.CoreMethod; | ||
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode; | ||
import org.jruby.truffle.builtins.CoreMethodNode; | ||
import org.jruby.truffle.builtins.UnaryCoreMethodNode; | ||
import org.jruby.truffle.core.cast.DurationToMillisecondsNodeGen; | ||
import org.jruby.truffle.core.thread.ThreadManager.BlockingAction; | ||
import org.jruby.truffle.language.RubyNode; | ||
import org.jruby.truffle.language.control.RaiseException; | ||
import org.jruby.truffle.language.objects.AllocateObjectNode; | ||
import org.jruby.truffle.language.objects.AllocateObjectNodeGen; | ||
|
||
@CoreClass("ConditionVariable") | ||
public abstract class ConditionVariableNodes { | ||
|
||
private static Object getCondition(DynamicObject conditionVariable) { | ||
return Layouts.CONDITION_VARIABLE.getCondition(conditionVariable); | ||
} | ||
|
||
@CoreMethod(names = "allocate", constructor = true) | ||
public abstract static class AllocateNode extends CoreMethodArrayArgumentsNode { | ||
|
||
@Child private AllocateObjectNode allocateNode; | ||
|
||
public AllocateNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
allocateNode = AllocateObjectNodeGen.create(context, sourceSection, null, null); | ||
} | ||
|
||
@Specialization | ||
public DynamicObject allocate(DynamicObject rubyClass) { | ||
return allocateNode.allocate(rubyClass, new Object()); | ||
} | ||
|
||
} | ||
|
||
@NodeChildren({ | ||
@NodeChild(value = "conditionVariable", type = RubyNode.class), | ||
@NodeChild(value = "mutex", type = RubyNode.class), | ||
@NodeChild(value = "duration", type = RubyNode.class) | ||
}) | ||
@CoreMethod(names = "wait", required = 1, optional = 1) | ||
public abstract static class WaitNode extends CoreMethodNode { | ||
|
||
@CreateCast("duration") | ||
public RubyNode coerceDuration(RubyNode duration) { | ||
return DurationToMillisecondsNodeGen.create(duration); | ||
} | ||
|
||
@Specialization(guards = "isRubyMutex(mutex)") | ||
public DynamicObject wait(DynamicObject conditionVariable, DynamicObject mutex, long timeoutInMillis) { | ||
final ReentrantLock lock = Layouts.MUTEX.getLock(mutex); | ||
final DynamicObject thread = getContext().getThreadManager().getCurrentThread(); | ||
final Object condition = getCondition(conditionVariable); | ||
|
||
doWait(timeoutInMillis, lock, thread, condition); | ||
|
||
return conditionVariable; | ||
} | ||
|
||
@TruffleBoundary | ||
private void doWait(final long durationInMillis, ReentrantLock lock, DynamicObject thread, Object condition) { | ||
final long start = System.currentTimeMillis(); | ||
|
||
// First lock the condition so we only release the Mutex when we are in wait() and ready to be notified | ||
synchronized (condition) { | ||
MutexOperations.unlock(lock, thread, this); | ||
try { | ||
getContext().getThreadManager().runUntilResult(this, new BlockingAction<Boolean>() { | ||
@Override | ||
public Boolean block() throws InterruptedException { | ||
long now = System.currentTimeMillis(); | ||
long slept = now - start; | ||
|
||
if (slept >= durationInMillis) { | ||
return SUCCESS; | ||
} | ||
|
||
condition.wait(durationInMillis - slept); | ||
return SUCCESS; | ||
} | ||
}); | ||
} finally { | ||
MutexOperations.lock(lock, thread, this); | ||
} | ||
} | ||
} | ||
} | ||
|
||
@CoreMethod(names = "signal") | ||
public abstract static class SignalNode extends UnaryCoreMethodNode { | ||
|
||
@Specialization | ||
public DynamicObject doSignal(DynamicObject conditionVariable) { | ||
final Object condition = getCondition(conditionVariable); | ||
synchronized (condition) { | ||
condition.notify(); | ||
} | ||
return conditionVariable; | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "broadcast") | ||
public abstract static class BroadcastNode extends UnaryCoreMethodNode { | ||
|
||
@Specialization | ||
public DynamicObject doBroadcast(DynamicObject conditionVariable) { | ||
final Object condition = getCondition(conditionVariable); | ||
synchronized (condition) { | ||
condition.notifyAll(); | ||
} | ||
return conditionVariable; | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "marshal_dump") | ||
public abstract static class MarshalDumpNode extends CoreMethodArrayArgumentsNode { | ||
|
||
@Specialization | ||
public Object marshal_dump(DynamicObject self) { | ||
throw new RaiseException(coreExceptions().typeErrorCantDump(self, this)); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1dc8945
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍