Class TruffleSafepoint
Supporting Safepoints in a Language
Safepoints are explicitly polled by invoking the poll(Node)
method. Safepoints are
polled
with relaxed location or with exact location
.
A poll with a relaxed location is significantly more efficient than a poll with a precise
location as the compiler is able to move and combine the poll requests during compilation. A
Truffle guest language implementation must ensure that a safepoint is polled repeatedly within a
constant time interval. For example, a single arithmetic expression completes within a constant
number of CPU cycles. However, a loop that summarizes values over an array uses a non-constant
time dependent on the array size. This typically means that safepoints are best polled at the end
of loops and at the end of function or method calls to cover recursion. In addition, any guest
language code that blocks the execution, like guest language locks, need to use the
blocking API
to
allow polling of safepoints while the thread is waiting.
Truffle's loop node
and root node
support safepoint polling
automatically. No further calls to poll(Node)
are therefore necessary. Custom loops or
loops behind boundary
annotated method calls are expected to be notified
by the guest language implementation manually.
Thread local actions optionally incur side-effects. By default side-effects are enabled. A
language implementation may disable side-effects temporarily for the current thread using
setAllowSideEffects(boolean)
method.
Submitting thread local actions
See ThreadLocalAction
for details on how to submit actions.
Further information can be found in the safepoint tutorial.
- Since:
- 21.1
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interface
Just likeTruffleSafepoint.Interruptible
but allows partial evaluation.static interface
Just likeTruffleSafepoint.InterruptibleFunction
but allows partial evaluation.static interface
An interrupter allows a foreign thread to interrupt the execution on a separate thread.static interface
Function interface that represent interruptable Java methods.static interface
Function interface that represent interruptable Java methods. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotected
TruffleSafepoint
(com.oracle.truffle.api.impl.Accessor.EngineSupport support) Do not extend this class. -
Method Summary
Modifier and TypeMethodDescriptionstatic TruffleSafepoint
Returns the current safepoint configuration for the current thread.abstract boolean
Returns whether there is any pending side-effecting thread local action on this thread, due to being in a critical section usingsetAllowSideEffects(boolean)
.static void
Polls a safepoint at the provided location.static void
Similar topoll(Node)
but with exact location.abstract boolean
setAllowActions
(boolean enabled) Allows to temporarily delay all thread local actions on the current thread.abstract boolean
setAllowSideEffects
(boolean enabled) Allows to temporarily delay side-effecting thread local actions on the current thread.abstract <T> void
setBlocked
(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.Interruptible<T> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt) abstract <T,
R> R setBlockedFunction
(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.InterruptibleFunction<T, R> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt) Transitions the current thread into a blocked state and calls an interruptible functional method.static <T> void
setBlockedThreadInterruptible
(Node location, TruffleSafepoint.Interruptible<T> interruptible, T object) Short-cut method to allow setting the blocked status for methods that throwInterruptedException
and support interrupting usingThread.interrupt()
.static <T,
R> R setBlockedThreadInterruptibleFunction
(Node location, TruffleSafepoint.InterruptibleFunction<T, R> interruptible, T object) Short-cut method to allow setting the blocked status for methods that throwInterruptedException
and support interrupting usingThread.interrupt()
.<T> void
setBlockedWithException
(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.Interruptible<T> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt) Deprecated.
-
Constructor Details
-
TruffleSafepoint
protected TruffleSafepoint(com.oracle.truffle.api.impl.Accessor.EngineSupport support) Do not extend this class. This class is intended to be implemented by a Truffle runtime implementation.- Since:
- 21.1
-
-
Method Details
-
poll
Polls a safepoint at the provided location. This allows to run thread local actions at this location. A Truffle guest language implementation must ensure that a safepoint is polled repeatedly within a constant time interval. SeeTruffleSafepoint
for further details.In compiled code calls to this method are removed. Instead the compiler inserts safepoints automatically at loop ends and method exits. In this case the node location is approximated by frame state of method ends and loop exits in the compiler IR. For method ends the parent root node and for loop exits the loop node is passed as location.
Guest language exceptions may be thrown by this method. If
side-effects
are allowed then also guest language exceptions may be thrown. Otherwise only internal orthread-death
exceptions may be thrown. This method is safe to be used on compiled code paths. Polling may be performed on threads without entered polyglot context, polls are ignored there.Example usage with an unbounded loop sum behind a
CompilerDirectives.TruffleBoundary
.@TruffleBoundary int sum(int[] array) { int sum = 0; for (int i = 0; i < array.length; i++) { sum += array[i]; TruffleSafepoint.poll(); } return sum; }
- Parameters:
location
- the location of the poll. May benull
, but it is recommended to always pass a location node, if available.- Since:
- 21.1
- See Also:
-
pollHere
Similar topoll(Node)
but with exact location. A poll withrelaxed location
is significantly more efficient than a poll with precise location as the compiler is able to move and combine the poll requests during compilation. This method is safe to be used on compiled code paths.Usage example:
TruffleSafepoint safepoint = TruffleSafepoint.getCurrent(); boolean prev = safepoint.setAllowSideEffects(false); try { // criticial section } finally { safepoint.setAllowSideEffects(prev); TruffleSafepoint.pollHere(this); }
- Parameters:
location
- the location of the poll. Must not benull
.- Since:
- 21.1
- See Also:
-
setBlockedWithException
@Deprecated public <T> void setBlockedWithException(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.Interruptible<T> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt) Transitions the current thread into a blocked state and calls an interruptible functional method. The blocked state is restored when the interruptible method returns. Setting the blocked state allows safepoint notification while the current thread is blocked. This allows Truffle to interrupt e.g. locks temporarily to perform a thread local action.The
location>
parameter is usedpoll
all pending thread local actions before transition to blocked state.The
interrupter
parameter specifies how the blocked state can be interrupted from another thread. The interrupter allows to interrupt the blocked state from other threads. For most blocking java.util.concurrent primitives thethread interrupter
can be used. If the thread will be blocked in native code, other ways of interrupting, like signals may be used by implementing theTruffleSafepoint.Interrupter
interface.The
interruptible
parameter provides the method that calls the blocking method which throwsInterruptedException
on interrupt. In order to avoid allocations of the functional interface a single argument can be provided that is passed to the interface. This is typically thelock
orsemaphore
instance. The implementation of this method is expected to throw anInterruptedException
if theTruffleSafepoint.Interrupter.interrupt(Thread)
method is invoked for this thread. For most java.util.concurrent primitives this is supported by using the interruptible blocking method variant, for exampleLock.lockInterruptibly()
.Since it is common to use this method with method reference syntax e.g.
Lock::lockInterruptibly
for the interruptible parameter, we implicitlely apply aboundary
for the entire method call by default. If the interruptible is called from a compiled code path and the interruptible should get partial evaluated, thenTruffleSafepoint.CompiledInterruptible
should be used instead ofTruffleSafepoint.Interruptible
. In this case the parameter must be apartial evaluation constant
.The
beforeInterrupt
runnable
andafterInterrupt
consumer
optional parameters allow to run code before and after a thread got interrupted and safepoint events are processed. Ifnull
is provided then no action will be performed. Arbitrary code may be executed in this runnable. Note that the blocked state is temporarily reset to its previous state while the afterInterrupt is called.If an exception is thrown during the processing of the safepoint,
afterInterrupt
will receive the throwable as argument, ornull
if the safepoint successfully completed. This exception will still be thrown after completion ofafterInterrupt
, unlessafterInterrupt
throws an exception of its own.Multiple recursive invocations of this method is supported. The previous blocked state will be restored when the method completes or fails.
Example usage:
Note there is a short-cut method to achieve the same behavior as in this example
setBlockedThreadInterruptible(Node, Interruptible, Object)
.Lock lock = new ReentrantLock(); TruffleSafepoint sp = TruffleSafepoint.getCurrent(); sp.setBlocked(location, Interrupter.THREAD_INTERRUPT, ReentrantLock::lockInterruptibly, lock, null, null);
- Since:
- 22.1
- See Also:
-
setBlockedFunction
public abstract <T,R> R setBlockedFunction(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.InterruptibleFunction<T, R> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt) Transitions the current thread into a blocked state and calls an interruptible functional method. The blocked state is restored when the interruptible method returns. Setting the blocked state allows safepoint notification while the current thread is blocked. This allows Truffle to interrupt e.g. locks temporarily to perform a thread local action.The
location
parameter is used topoll
all pending thread local actions before transition to blocked state. It may benull
, but it is recommended to always pass a location node, if available.The
interrupter
parameter specifies how the blocked state can be interrupted from another thread. The interrupter allows to interrupt the blocked state from other threads. For most blocking java.util.concurrent primitives thethread interrupter
can be used. If the thread will be blocked in native code, other ways of interrupting, like signals may be used by implementing theTruffleSafepoint.Interrupter
interface.The
interruptible
parameter provides the method that calls the blocking method which throwsInterruptedException
on interrupt. In order to avoid allocations of the functional interface a single argument can be provided that is passed to the interface. This is typically thelock
orsemaphore
instance. The implementation of this method is expected to throw anInterruptedException
if theTruffleSafepoint.Interrupter.interrupt(Thread)
method is invoked for this thread. For most java.util.concurrent primitives this is supported by using the interruptible blocking method variant, for exampleLock.lockInterruptibly()
.boundary
is applied for the entire interruptible method call by default. If the interruptible is called from a compiled code path and the interruptible should get partial evaluated, thenTruffleSafepoint.CompiledInterruptibleFunction
should be used instead ofTruffleSafepoint.InterruptibleFunction
. In this case the parameter must be apartial evaluation constant
.The
beforeInterrupt
runnable
andafterInterrupt
consumer
optional parameters allow to run code before and after a thread got interrupted and safepoint events are processed. Ifnull
is provided then no action will be performed. Arbitrary code may be executed in this runnable. Note that the blocked state is temporarily reset to its previous state while the afterInterrupt is called.If an exception is thrown during the processing of the safepoint,
afterInterrupt
will receive the throwable as argument, ornull
if the safepoint successfully completed. This exception will still be thrown after completion ofafterInterrupt
, unlessafterInterrupt
throws an exception of its own.Multiple recursive invocations of this method is supported. The previous blocked state will be restored when the method completes or fails.
Example usage:
Note there is a short-cut method to achieve the same behavior as in this example
setBlockedThreadInterruptibleFunction(Node, InterruptibleFunction, Object)
.Queue<Object> queue = new ArrayBlockingQueue<>(10); TruffleSafepoint sp = TruffleSafepoint.getCurrent(); sp.setBlockedFunction(location, Interrupter.THREAD_INTERRUPT, BlockingQueue::take, queue, null, null);
- Since:
- 23.1
- See Also:
-
setBlocked
public abstract <T> void setBlocked(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.Interruptible<T> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt) The same assetBlockedFunction(Node, Interrupter, InterruptibleFunction, Object, Runnable, Consumer)
. The only difference is that the interruptible functional method does not return anything.- Since:
- 23.1
-
setBlockedThreadInterruptible
public static <T> void setBlockedThreadInterruptible(Node location, TruffleSafepoint.Interruptible<T> interruptible, T object) Short-cut method to allow setting the blocked status for methods that throwInterruptedException
and support interrupting usingThread.interrupt()
.- Parameters:
location
- the location with which the safepoint should be polled.interruptible
- the thread interruptable method to use for locking the objectobject
- the instance to use the interruptable method with.- Since:
- 21.1
-
setBlockedThreadInterruptibleFunction
public static <T,R> R setBlockedThreadInterruptibleFunction(Node location, TruffleSafepoint.InterruptibleFunction<T, R> interruptible, T object) Short-cut method to allow setting the blocked status for methods that throwInterruptedException
and support interrupting usingThread.interrupt()
.- Parameters:
location
- the location with which the safepoint should be polled.interruptible
- the thread interruptable method to use for locking the objectobject
- the instance to use the interruptable method with.- Since:
- 23.1
-
setAllowActions
Allows to temporarily delay all thread local actions on the current thread. It is recommended to delay actions only for a constant period of time and while trusted and internal guest code is running. Please consider usingsetAllowSideEffects(boolean)
before using this method. While actions are disabled the value ofsetAllowSideEffects(boolean)
has no effect. Whenactions
are enabled again the value ofsetAllowSideEffects(boolean)
will be interpreted again.Currently this method may only be used during
context finalization
. This could be necessary to free up native resources through guest code when a context is cancelled to avoid resource leakage. Any usage of this method should be subject to a detailed security review to ensure only internal and well-known guest code is executed. Disabling thread local actions may delay thread local actions like exit, cancellation and interruption.Example usage:
TruffleSafepoint sp = TruffleSafepoint.getCurrent(); boolean prev = sp.setAllowActions(false); try { // critical section } finally { sp.setAllowActions(prev); }
- Throws:
IllegalStateException
- if allow actions can currently not be set, for example outside the scope of acontext finalization
.- Since:
- 22.1
- See Also:
-
setAllowSideEffects
public abstract boolean setAllowSideEffects(boolean enabled) Allows to temporarily delay side-effecting thread local actions on the current thread. It is recommended to delay side-effecting actions only for a short and constant period of time.While side-effecting thread local actions are delayed on this thread, only non-side-effecting thread local actions will be scheduled in this thread. Non-side-effecting thread local actions do not mutate guest objects, run guest code or throw guest exceptions, but they might still throw internal errors.
Example usage:
TruffleSafepoint sp = TruffleSafepoint.getCurrent(); boolean prev = sp.setAllowSideEffects(false); try { // critical section } finally { sp.setAllowSideEffects(prev); }
- Since:
- 21.1
-
hasPendingSideEffectingActions
public abstract boolean hasPendingSideEffectingActions()Returns whether there is any pending side-effecting thread local action on this thread, due to being in a critical section usingsetAllowSideEffects(boolean)
. When side-effecting actions are allowed, this method always returnsfalse
.This is useful if the language exposes a way to know if there are any pending side-effecting thread local action due to using
setAllowSideEffects(boolean)
.- Since:
- 21.1
-
getCurrent
Returns the current safepoint configuration for the current thread. This method is useful to access configuration methods likesetBlocked(Node, Interrupter, Interruptible, Object, Runnable, Consumer)
orsetAllowSideEffects(boolean)
.Important: The result of this method must not be stored or used on a different thread than the current thread.
- Throws:
IllegalStateException
- if the current thread is not entered with a polyglot context.- Since:
- 21.1
-
setBlocked(Node, Interrupter, Interruptible, Object, Runnable, Consumer)