From 7f55db72d2c2be3d0e3396dc8a4ba8ca1f504fd3 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Mon, 1 Apr 2019 13:58:41 +0100 Subject: Yengine: try fix changing scripts running state if the have long events --- OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs | 27 +++++++++- OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs | 27 +++++++++- OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs | 57 +++++++++++++++------- .../Region/ScriptEngine/YEngine/XMRScriptThread.cs | 8 ++- 4 files changed, 96 insertions(+), 23 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs index 6acc293..e1f8c4c 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs @@ -1535,15 +1535,38 @@ namespace OpenSim.Region.ScriptEngine.Yengine */ public void QueueToStart(XMRInstance inst) { - if(inst.m_IState != XMRInstState.ONSTARTQ) + if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); - lock(m_StartQueue) + lock (m_StartQueue) m_StartQueue.InsertTail(inst); WakeUpOne(); } + public void QueueToYield(XMRInstance inst) + { + if (inst.m_IState != XMRInstState.ONYIELDQ) + throw new Exception("bad state"); + + lock (m_YieldQueue) + m_YieldQueue.InsertTail(inst); + + WakeUpOne(); + } + + public void RemoveFromSleep(XMRInstance inst) + { + lock (m_SleepQueue) + { + if (inst.m_IState != XMRInstState.ONSLEEPQ) + return; + + m_SleepQueue.Remove(inst); + inst.m_IState = XMRInstState.REMDFROMSLPQ; + } + } + /** * @brief A script may be sleeping, in which case we wake it. */ diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs index 12feb7b..ff8dae5 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstMisc.cs @@ -363,8 +363,33 @@ namespace OpenSim.Region.ScriptEngine.Yengine lock(m_QueueLock) { m_Running = value; - if(!value) + if(value) { + if (m_IState == XMRInstState.SUSPENDED && m_SuspendCount == 0) + { + if(eventCode != ScriptEventCode.None) + { + m_IState = XMRInstState.ONYIELDQ; + m_Engine.QueueToYield(this); + } + else if ((m_EventQueue != null) && (m_EventQueue.First != null)) + { + m_IState = XMRInstState.ONSTARTQ; + m_Engine.QueueToStart(this); + } + else + m_IState = XMRInstState.IDLE; + } + else if(m_SuspendCount != 0) + m_IState = XMRInstState.IDLE; + } + else + { + if(m_IState == XMRInstState.ONSLEEPQ) + { + m_Engine.RemoveFromSleep(this); + m_IState = XMRInstState.SUSPENDED; + } EmptyEventQueues(); } } diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs index d237d2c..4f94c23 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs @@ -80,10 +80,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine !m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state return; - // Not running means we ignore any incoming events. - // But queue if still constructing because m_Running is not yet valid. + // Not running means we ignore any incoming events. + // But queue if still constructing because m_Running is not yet valid. + if(!m_Running && !construct) + { + if(m_IState == XMRInstState.SUSPENDED) + { + if(evc == ScriptEventCode.state_entry && m_EventQueue.Count == 0) + { + LinkedListNode llns = new LinkedListNode(evt); + m_EventQueue.AddFirst(llns); + } + } return; + } if(m_minEventDelay != 0) { @@ -250,13 +261,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine return XMRInstState.SUSPENDED; } - // Make sure we aren't being migrated in or out and prevent that - // whilst we are in here. If migration has it locked, don't call - // back right away, delay a bit so we don't get in infinite loop. + // Make sure we aren't being migrated in or out and prevent that + // whilst we are in here. If migration has it locked, don't call + // back right away, delay a bit so we don't get in infinite loop. m_RunOnePhase = "lock m_RunLock"; if(!Monitor.TryEnter(m_RunLock)) { - m_SleepUntil = now.AddMilliseconds(3); + m_SleepUntil = now.AddMilliseconds(15); m_RunOnePhase = "return was locked"; return XMRInstState.ONSLEEPQ; } @@ -273,6 +284,12 @@ namespace OpenSim.Region.ScriptEngine.Yengine return XMRInstState.DISPOSED; } + if(!m_Running) + { + m_RunOnePhase = "return is not running"; + return XMRInstState.SUSPENDED; + } + // Do some more of the last event if it didn't finish. if(this.eventCode != ScriptEventCode.None) { @@ -325,10 +342,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine if(m_EventQueue.First != null) { evt = m_EventQueue.First.Value; - if(m_DetachQuantum > 0) + evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt.EventName); + if (m_DetachQuantum > 0) { - evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), - evt.EventName); if(evc != ScriptEventCode.attach) { // This is the case where the attach event @@ -343,8 +359,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine } } m_EventQueue.RemoveFirst(); - evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), - evt.EventName); if((int)evc >= 0) m_EventCounts[(int)evc]--; } @@ -730,11 +744,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine case XMRInstState.DISPOSED: return; - // Some other thread is already resetting it, let it finish. + // Some other thread is already resetting it, let it finish. case XMRInstState.RESETTING: return; + case XMRInstState.SUSPENDED: + break; + default: throw new Exception("bad state"); } @@ -744,17 +761,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine { CheckRunLockInvariants(true); - // No other thread should have transitioned it from RESETTING. - if(m_IState != XMRInstState.RESETTING) - throw new Exception("bad state"); + // No other thread should have transitioned it from RESETTING. + if (m_IState != XMRInstState.SUSPENDED) + { + if (m_IState != XMRInstState.RESETTING) + throw new Exception("bad state"); - // Mark it idle now so it can get queued to process new stuff. - m_IState = XMRInstState.IDLE; + m_IState = XMRInstState.IDLE; + } - // Reset everything and queue up default's start_entry() event. + // Reset everything and queue up default's start_entry() event. ClearQueue(); ResetLocked("external Reset"); + // Mark it idle now so it can get queued to process new stuff. + CheckRunLockInvariants(true); } } diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs index 08c7e80..f68fd51 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRScriptThread.cs @@ -166,7 +166,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine if(inst == null) break; - if(inst.m_IState != XMRInstState.ONSTARTQ) + if (inst.m_IState == XMRInstState.SUSPENDED) + continue; + if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); RunInstance(inst, tid); if(m_SuspendScriptThreadFlag || m_Exiting) @@ -187,7 +189,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine if(inst != null) { - if(inst.m_IState != XMRInstState.ONYIELDQ) + if (inst.m_IState == XMRInstState.SUSPENDED) + continue; + if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state"); RunInstance(inst, tid); continue; -- cgit v1.1