From a810ee85dc38c94acdfb2f50c7aff8f61b0d3500 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Wed, 25 Sep 2024 15:00:32 +0200 Subject: [PATCH] Resolving conflicts in PolyglotContextImpl.java --- .../truffle/polyglot/PolyglotContextImpl.java | 232 +++++++++--------- 1 file changed, 120 insertions(+), 112 deletions(-) diff --git a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java index 53ed78216a71b..5e7fc5678d64e 100644 --- a/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java +++ b/truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/PolyglotContextImpl.java @@ -825,6 +825,8 @@ Object[] enterThreadChanged(boolean enterReverted, boolean pollSafepoint, boolea Object[] prev = null; Thread current = Thread.currentThread(); try { + for (;;) { + try { boolean deactivateSafepoints = mustSucceed; boolean localPollSafepoint = pollSafepoint && !mustSucceed; try { @@ -840,7 +842,7 @@ Object[] enterThreadChanged(boolean enterReverted, boolean pollSafepoint, boolea synchronized (this) { PolyglotThreadInfo threadInfo = getCurrentThreadInfo(); - if (enterReverted && threadInfo.getEnteredCount() == 0) { + 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); @@ -851,136 +853,142 @@ Object[] enterThreadChanged(boolean enterReverted, boolean pollSafepoint, boolea threadInfo.interruptSent = false; } notifyAll(); - } - } - if (deactivateSafepoints && threadInfo != PolyglotThreadInfo.NULL) { - threadLocalActions.notifyThreadActivation(threadInfo, false); - } - - assert threadInfo != null; - if (!leaveAndEnter) { - checkClosedOrDisposing(mustSucceed); - if (threadInfo.isInLeaveAndEnter()) { - throw PolyglotEngineException.illegalState("Context cannot be entered inside leaveAndEnter."); - } - } + } + } + if (deactivateSafepoints && threadInfo != PolyglotThreadInfo.NULL) { + threadLocalActions.notifyThreadActivation(threadInfo, false); + } - threadInfo = threads.get(current); - if (threadInfo == null) { - threadInfo = createThreadInfo(current, polyglotThreadFirstEnter); - 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, false); + assert threadInfo != null; + if (!leaveAndEnter) { + checkClosedOrDisposing(mustSucceed); + if (threadInfo.isInLeaveAndEnter()) { + throw PolyglotEngineException.illegalState("Context cannot be entered inside leaveAndEnter."); + } + } - if (transitionToMultiThreading) { - // recheck all thread accesses - checkAllThreadAccesses(Thread.currentThread(), false); - } + threadInfo = threads.get(current); + if (threadInfo == null) { + threadInfo = createThreadInfo(current, polyglotThreadFirstEnter); + 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, 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 (transitionToMultiThreading) { + // recheck all thread accesses + checkAllThreadAccesses(Thread.currentThread(), false); + } - if (needsInitialization) { - threads.put(current, threadInfo); - } + 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) { - /* - * Do not enter the thread before initializing thread locals. Creation of - * thread locals might fail. - */ - initializeThreadLocals(threadInfo); - } + if (needsInitialization) { + threads.put(current, threadInfo); + } - prev = threadInfo.enterInternal(); - if (leaveAndEnter) { - threadInfo.setLeaveAndEnterInterrupter(null); - notifyAll(); - } - if (needsInitialization) { - this.threadLocalActions.notifyEnterCreatedThread(); - } - if (closingThread != Thread.currentThread()) { - try { - threadInfo.notifyEnter(engine, this); - } catch (Throwable t) { - threadInfo.leaveInternal(prev); - throw t; - } - } - enteredThread = threadInfo; + if (needsInitialization) { + /* + * Do not enter the thread before initializing thread locals. + * Creation of thread locals might fail. + */ + initializeThreadLocals(threadInfo); + } - // new thread became active so we need to check potential active thread local - // actions and process them. - Set activatedActions = null; - if (enteredThread.getEnteredCount() == 1 && !deactivateSafepoints) { - activatedActions = threadLocalActions.notifyThreadActivation(threadInfo, true); - } + prev = threadInfo.enterInternal(); + if (leaveAndEnter) { + threadInfo.setLeaveAndEnterInterrupter(null); + notifyAll(); + } + if (needsInitialization) { + this.threadLocalActions.notifyEnterCreatedThread(); + } + if (closingThread != Thread.currentThread()) { + try { + threadInfo.notifyEnter(engine, this); + } catch (Throwable t) { + threadInfo.leaveInternal(prev); + throw t; + } + } + enteredThread = threadInfo; + + // new thread became active so we need to check potential active thread + // local + // actions and process them. + Set 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(mustSucceed); - } + if (transitionToMultiThreading) { + // we need to verify that all languages give access + // to all threads in multi-threaded mode. + transitionToMultiThreaded(mustSucceed); + } - if (needsInitialization) { - initializeNewThread(enteredThread, mustSucceed); - } + if (needsInitialization) { + initializeNewThread(enteredThread, mustSucceed); + } - if (enteredThread.getEnteredCount() == 1 && !pauseHandles.isEmpty()) { - for (Iterator pauseHandleIterator = pauseHandles.iterator(); pauseHandleIterator.hasNext();) { - ContextPauseHandle pauseHandle = pauseHandleIterator.next(); - if (!pauseHandle.pauseThreadLocalAction.isPause() || pauseHandle.isCancelled()) { - pauseHandleIterator.remove(); - } else { - if (activatedActions == null || !activatedActions.contains(pauseHandle.pauseThreadLocalAction)) { - threadLocalActions.submit(new Thread[]{Thread.currentThread()}, PolyglotEngineImpl.ENGINE_ID, pauseHandle.pauseThreadLocalAction, - new HandshakeConfig(true, true, false, false)); + if (enteredThread.getEnteredCount() == 1 && !pauseHandles.isEmpty()) { + for (Iterator pauseHandleIterator = pauseHandles.iterator(); pauseHandleIterator.hasNext();) { + ContextPauseHandle pauseHandle = pauseHandleIterator.next(); + if (!pauseHandle.pauseThreadLocalAction.isPause() || pauseHandle.isCancelled()) { + pauseHandleIterator.remove(); + } else { + if (activatedActions == null || !activatedActions.contains(pauseHandle.pauseThreadLocalAction)) { + threadLocalActions.submit(new Thread[]{Thread.currentThread()}, PolyglotEngineImpl.ENGINE_ID, pauseHandle.pauseThreadLocalAction, + new HandshakeConfig(true, true, false, false)); + } + } } } - } - } // never cache last thread on close or when closingThread setCachedThreadInfo(threadInfo); - if (needsInitialization && !threadInfo.isPolyglotThread()) { - deadThreads = collectDeadThreads(); - } - } + if (needsInitialization && !threadInfo.isPolyglotThread()) { + deadThreads = collectDeadThreads(); + } + } - if (deadThreads != null) { - finalizeAndDisposeThreads(deadThreads); - } + if (deadThreads != null) { + finalizeAndDisposeThreads(deadThreads); + } - if (needsInitialization) { - EngineAccessor.INSTRUMENT.notifyThreadStarted(engine, creatorTruffleContext, current); - } + 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 (localPollSafepoint && enteredThread != null) { - TruffleSafepoint.pollHere(this.uncachedLocation); + 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 (localPollSafepoint && enteredThread != null) { + TruffleSafepoint.pollHere(this.uncachedLocation); + } + } + } catch (PolyglotThreadAccessException ex) { + ex.rethrow(this); } } } catch (Throwable t) {