Search in sources :

Example 1 with HandshakeConfig

use of com.oracle.truffle.polyglot.PolyglotThreadLocalActions.HandshakeConfig in project graal by oracle.

the class PolyglotContextImpl method enterThreadChanged.

/**
 * Use to enter context if it's guaranteed to be called rarely and configuration flexibility is
 * needed. Otherwise use {@link PolyglotEngineImpl#enter(PolyglotContextImpl)}.
 */
@TruffleBoundary
Object[] enterThreadChanged(boolean notifyEnter, boolean enterReverted, boolean pollSafepoint, boolean deactivateSafepoints) {
    PolyglotThreadInfo enteredThread = null;
    Object[] prev = null;
    try {
        Thread current = Thread.currentThread();
        boolean needsInitialization = false;
        synchronized (this) {
            PolyglotThreadInfo threadInfo = getCurrentThreadInfo();
            if (enterReverted && threadInfo.getEnteredCount() == 0) {
                threadLocalActions.notifyThreadActivation(threadInfo, false);
                if ((state.isCancelling() || state.isExiting() || state == State.CLOSED_CANCELLED || state == State.CLOSED_EXITED) && !threadInfo.isActive()) {
                    notifyThreadClosed(threadInfo);
                }
                if (state.isInterrupting() && !threadInfo.isActive()) {
                    Thread.interrupted();
                    notifyAll();
                }
            }
            if (deactivateSafepoints && threadInfo != PolyglotThreadInfo.NULL) {
                threadLocalActions.notifyThreadActivation(threadInfo, false);
            }
            checkClosed();
            assert threadInfo != null;
            threadInfo = threads.get(current);
            if (threadInfo == null) {
                threadInfo = createThreadInfo(current);
                needsInitialization = true;
            }
            if (singleThreaded) {
                /*
                     * If this is the only thread, then setting the cached thread info to NULL is no
                     * performance problem. If there is other thread that is just about to enter, we
                     * are making sure that it initializes multi-threading if this thread doesn't do
                     * it.
                     */
                setCachedThreadInfo(PolyglotThreadInfo.NULL);
            }
            boolean transitionToMultiThreading = isSingleThreaded() && hasActiveOtherThread(true);
            if (transitionToMultiThreading) {
                // recheck all thread accesses
                checkAllThreadAccesses(Thread.currentThread(), false);
            }
            if (transitionToMultiThreading) {
                /*
                     * We need to do this early (before initializeMultiThreading) as entering or
                     * local initialization depends on single thread per context.
                     */
                engine.singleThreadPerContext.invalidate();
                singleThreaded = false;
            }
            if (needsInitialization) {
                threads.put(current, threadInfo);
            }
            if (needsInitialization) {
                /*
                     * Do not enter the thread before initializing thread locals. Creation of thread
                     * locals might fail.
                     */
                initializeThreadLocals(threadInfo);
            }
            prev = threadInfo.enterInternal();
            if (notifyEnter) {
                try {
                    threadInfo.notifyEnter(engine, this);
                } catch (Throwable t) {
                    threadInfo.leaveInternal(prev);
                    throw t;
                }
            }
            enteredThread = threadInfo;
            if (needsInitialization) {
                this.threadLocalActions.notifyEnterCreatedThread();
            }
            // new thread became active so we need to check potential active thread local
            // actions and process them.
            Set<ThreadLocalAction> activatedActions = null;
            if (enteredThread.getEnteredCount() == 1 && !deactivateSafepoints) {
                activatedActions = threadLocalActions.notifyThreadActivation(threadInfo, true);
            }
            if (transitionToMultiThreading) {
                // we need to verify that all languages give access
                // to all threads in multi-threaded mode.
                transitionToMultiThreaded();
            }
            if (needsInitialization) {
                initializeNewThread(current);
            }
            if (enteredThread.getEnteredCount() == 1 && !pauseThreadLocalActions.isEmpty()) {
                for (Iterator<PauseThreadLocalAction> threadLocalActionIterator = pauseThreadLocalActions.iterator(); threadLocalActionIterator.hasNext(); ) {
                    PauseThreadLocalAction threadLocalAction = threadLocalActionIterator.next();
                    if (!threadLocalAction.isPause()) {
                        threadLocalActionIterator.remove();
                    } else {
                        if (activatedActions == null || !activatedActions.contains(threadLocalAction)) {
                            threadLocalActions.submit(new Thread[] { Thread.currentThread() }, PolyglotEngineImpl.ENGINE_ID, threadLocalAction, new HandshakeConfig(true, true, false, false));
                        }
                    }
                }
            }
            // never cache last thread on close or when closingThread
            setCachedThreadInfo(threadInfo);
        }
        if (needsInitialization) {
            EngineAccessor.INSTRUMENT.notifyThreadStarted(engine, creatorTruffleContext, current);
        }
        return prev;
    } finally {
        /*
             * We need to always poll the safepoint here in case we already submitted a thread local
             * action for this thread. Not polling here would make dependencies of that event wait
             * forever.
             */
        if (pollSafepoint) {
            try {
                TruffleSafepoint.pollHere(this.uncachedLocation);
            } catch (Throwable t) {
                /*
                     * Just in case a safepoint makes the enter fail we need to leave the context
                     * again.
                     */
                if (enteredThread != null) {
                    this.leaveThreadChanged(prev, notifyEnter, true);
                }
                throw t;
            }
        }
    }
}
Also used : HandshakeConfig(com.oracle.truffle.polyglot.PolyglotThreadLocalActions.HandshakeConfig) TruffleObject(com.oracle.truffle.api.interop.TruffleObject) ThreadLocalAction(com.oracle.truffle.api.ThreadLocalAction) TruffleBoundary(com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)

Example 2 with HandshakeConfig

use of com.oracle.truffle.polyglot.PolyglotThreadLocalActions.HandshakeConfig in project graal by oracle.

the class PolyglotContextImpl method pause.

synchronized Future<Void> pause() {
    PauseThreadLocalAction pauseAction = new PauseThreadLocalAction(this);
    Future<Void> future = threadLocalActions.submit(null, PolyglotEngineImpl.ENGINE_ID, pauseAction, new HandshakeConfig(true, true, false, false));
    pauseThreadLocalActions.add(pauseAction);
    return new ContextPauseHandle(pauseAction, future);
}
Also used : HandshakeConfig(com.oracle.truffle.polyglot.PolyglotThreadLocalActions.HandshakeConfig)

Aggregations

HandshakeConfig (com.oracle.truffle.polyglot.PolyglotThreadLocalActions.HandshakeConfig)2 TruffleBoundary (com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)1 ThreadLocalAction (com.oracle.truffle.api.ThreadLocalAction)1 TruffleObject (com.oracle.truffle.api.interop.TruffleObject)1