diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs | 177 |
1 files changed, 167 insertions, 10 deletions
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs index aa8573c..7447f2f 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs | |||
@@ -99,7 +99,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
99 | new Dictionary<string,FieldInfo> (); | 99 | new Dictionary<string,FieldInfo> (); |
100 | private int m_StackSize; | 100 | private int m_StackSize; |
101 | private int m_HeapSize; | 101 | private int m_HeapSize; |
102 | |||
102 | private XMRScriptThread[] m_ScriptThreads; | 103 | private XMRScriptThread[] m_ScriptThreads; |
104 | private int m_WakeUpOne = 0; | ||
105 | public object m_WakeUpLock = new object(); | ||
106 | private Dictionary<Thread,XMRScriptThread> m_AllThreads = new Dictionary<Thread,XMRScriptThread> (); | ||
107 | |||
108 | private bool m_SuspendScriptThreadFlag = false; | ||
109 | /** | ||
110 | * @brief Something was just added to the Start or Yield queue so | ||
111 | * wake one of the XMRScriptThread instances to run it. | ||
112 | */ | ||
113 | |||
103 | private Thread m_SleepThread = null; | 114 | private Thread m_SleepThread = null; |
104 | private bool m_Exiting = false; | 115 | private bool m_Exiting = false; |
105 | 116 | ||
@@ -165,6 +176,36 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
165 | get { return scriptReferencedAssemblies; } | 176 | get { return scriptReferencedAssemblies; } |
166 | } | 177 | } |
167 | 178 | ||
179 | public void WakeUpOne() | ||
180 | { | ||
181 | lock (m_WakeUpLock) | ||
182 | { | ||
183 | m_WakeUpOne++; | ||
184 | Monitor.Pulse(m_WakeUpLock); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | public void AddThread(Thread thd, XMRScriptThread xthd) | ||
189 | { | ||
190 | lock(m_AllThreads) | ||
191 | m_AllThreads.Add(thd, xthd); | ||
192 | } | ||
193 | |||
194 | public void RemoveThread(Thread thd) | ||
195 | { | ||
196 | lock(m_AllThreads) | ||
197 | m_AllThreads.Remove(thd); | ||
198 | } | ||
199 | |||
200 | public XMRScriptThread CurrentScriptThread () | ||
201 | { | ||
202 | XMRScriptThread st; | ||
203 | lock (m_AllThreads) | ||
204 | m_AllThreads.TryGetValue (Thread.CurrentThread, out st); | ||
205 | |||
206 | return st; | ||
207 | } | ||
208 | |||
168 | public void Initialise(IConfigSource config) | 209 | public void Initialise(IConfigSource config) |
169 | { | 210 | { |
170 | TraceCalls("[XMREngine]: Initialize entry"); | 211 | TraceCalls("[XMREngine]: Initialize entry"); |
@@ -235,7 +276,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
235 | } | 276 | } |
236 | 277 | ||
237 | for (int i = 0; i < numThreadScriptWorkers; i ++) | 278 | for (int i = 0; i < numThreadScriptWorkers; i ++) |
238 | m_ScriptThreads[i] = new XMRScriptThread(this, i); | 279 | { |
280 | m_ScriptThreads[i] = new XMRScriptThread(this, i);; | ||
281 | } | ||
282 | |||
239 | 283 | ||
240 | m_SleepThread = StartMyThread(RunSleepThread, "xmrengine sleep", ThreadPriority.Normal); | 284 | m_SleepThread = StartMyThread(RunSleepThread, "xmrengine sleep", ThreadPriority.Normal); |
241 | 285 | ||
@@ -678,6 +722,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
678 | XMRScriptThread scriptThread = m_ScriptThreads[i]; | 722 | XMRScriptThread scriptThread = m_ScriptThreads[i]; |
679 | if (scriptThread != null) | 723 | if (scriptThread != null) |
680 | { | 724 | { |
725 | scriptThread.WakeUpScriptThread(); | ||
726 | Monitor.PulseAll (m_WakeUpLock); | ||
681 | scriptThread.Terminate(); | 727 | scriptThread.Terminate(); |
682 | m_ScriptThreads[i] = null; | 728 | m_ScriptThreads[i] = null; |
683 | } | 729 | } |
@@ -722,7 +768,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
722 | m_Scene.EventManager.TriggerEmptyScriptCompileQueue (0, ""); | 768 | m_Scene.EventManager.TriggerEmptyScriptCompileQueue (0, ""); |
723 | m_StartProcessing = true; | 769 | m_StartProcessing = true; |
724 | for (int i = 0; i < numThreadScriptWorkers; i ++) { | 770 | for (int i = 0; i < numThreadScriptWorkers; i ++) { |
725 | XMRScriptThread.WakeUpOne(); | 771 | WakeUpOne(); |
726 | } | 772 | } |
727 | m_log.Debug ("[XMREngine]: StartProcessing return"); | 773 | m_log.Debug ("[XMREngine]: StartProcessing return"); |
728 | } | 774 | } |
@@ -832,15 +878,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
832 | 878 | ||
833 | case "resume": | 879 | case "resume": |
834 | m_log.Info ("[XMREngine]: resuming scripts"); | 880 | m_log.Info ("[XMREngine]: resuming scripts"); |
881 | m_SuspendScriptThreadFlag = false; | ||
835 | for (int i = 0; i < numThreadScriptWorkers; i ++) | 882 | for (int i = 0; i < numThreadScriptWorkers; i ++) |
836 | m_ScriptThreads[i].ResumeThread(); | 883 | m_ScriptThreads[i].WakeUpScriptThread(); |
837 | 884 | Monitor.PulseAll(m_WakeUpLock); | |
838 | break; | 885 | break; |
839 | 886 | ||
840 | case "suspend": | 887 | case "suspend": |
841 | m_log.Info ("[XMREngine]: suspending scripts"); | 888 | m_log.Info ("[XMREngine]: suspending scripts"); |
889 | m_SuspendScriptThreadFlag = true; | ||
842 | for (int i = 0; i < numThreadScriptWorkers; i ++) | 890 | for (int i = 0; i < numThreadScriptWorkers; i ++) |
843 | m_ScriptThreads[i].SuspendThread(); | 891 | m_ScriptThreads[i].WakeUpScriptThread(); |
892 | Monitor.PulseAll(m_WakeUpLock); | ||
844 | break; | 893 | break; |
845 | 894 | ||
846 | case "tracecalls": | 895 | case "tracecalls": |
@@ -1545,7 +1594,14 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1545 | if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); | 1594 | if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); |
1546 | m_StartQueue.InsertTail(inst); | 1595 | m_StartQueue.InsertTail(inst); |
1547 | } | 1596 | } |
1548 | XMRScriptThread.WakeUpOne(); | 1597 | WakeUpOne(); |
1598 | } | ||
1599 | |||
1600 | public void QueueToTrunk(ThreadStart thds) | ||
1601 | { | ||
1602 | lock (m_WakeUpLock) | ||
1603 | m_ThunkQueue.Enqueue (thds); | ||
1604 | WakeUpOne(); | ||
1549 | } | 1605 | } |
1550 | 1606 | ||
1551 | /** | 1607 | /** |
@@ -1572,7 +1628,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1572 | 1628 | ||
1573 | 1629 | ||
1574 | // Make sure the OS thread is running so it will see the script. | 1630 | // Make sure the OS thread is running so it will see the script. |
1575 | XMRScriptThread.WakeUpOne(); | 1631 | WakeUpOne(); |
1576 | } | 1632 | } |
1577 | 1633 | ||
1578 | /** | 1634 | /** |
@@ -1724,7 +1780,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1724 | inst.m_IState = XMRInstState.ONYIELDQ; | 1780 | inst.m_IState = XMRInstState.ONYIELDQ; |
1725 | m_YieldQueue.InsertTail(inst); | 1781 | m_YieldQueue.InsertTail(inst); |
1726 | } | 1782 | } |
1727 | XMRScriptThread.WakeUpOne (); | 1783 | WakeUpOne (); |
1728 | } | 1784 | } |
1729 | } | 1785 | } |
1730 | 1786 | ||
@@ -1934,12 +1990,113 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1934 | 1990 | ||
1935 | public static void UpdateMyThread () | 1991 | public static void UpdateMyThread () |
1936 | { | 1992 | { |
1937 | Watchdog.UpdateThread (); | 1993 | Watchdog.UpdateThread(); |
1938 | } | 1994 | } |
1939 | 1995 | ||
1940 | public static void MyThreadExiting () | 1996 | public static void MyThreadExiting () |
1941 | { | 1997 | { |
1942 | Watchdog.RemoveThread (true); | 1998 | Watchdog.RemoveThread(true); |
1999 | } | ||
2000 | |||
2001 | public void RunScriptThread(XMRScriptThread xthd) | ||
2002 | { | ||
2003 | XMRInstance inst; | ||
2004 | while (!m_Exiting) | ||
2005 | { | ||
2006 | Watchdog.UpdateThread(); | ||
2007 | |||
2008 | /* | ||
2009 | * Handle 'xmr resume/suspend' commands. | ||
2010 | */ | ||
2011 | if (m_SuspendScriptThreadFlag) | ||
2012 | { | ||
2013 | lock (m_WakeUpLock) | ||
2014 | { | ||
2015 | while (m_SuspendScriptThreadFlag && | ||
2016 | !m_Exiting && | ||
2017 | (m_ThunkQueue.Count == 0)) | ||
2018 | { | ||
2019 | Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); | ||
2020 | XMREngine.UpdateMyThread (); | ||
2021 | } | ||
2022 | } | ||
2023 | } | ||
2024 | |||
2025 | /* | ||
2026 | * Maybe there are some scripts waiting to be migrated in or out. | ||
2027 | */ | ||
2028 | ThreadStart thunk = null; | ||
2029 | lock (m_WakeUpLock) | ||
2030 | { | ||
2031 | if (m_ThunkQueue.Count > 0) | ||
2032 | thunk = m_ThunkQueue.Dequeue (); | ||
2033 | } | ||
2034 | if (thunk != null) | ||
2035 | { | ||
2036 | inst = (XMRInstance)thunk.Target; | ||
2037 | thunk (); | ||
2038 | if (m_Exiting || m_SuspendScriptThreadFlag) | ||
2039 | continue; | ||
2040 | } | ||
2041 | |||
2042 | if (m_StartProcessing) | ||
2043 | { | ||
2044 | // If event just queued to any idle scripts | ||
2045 | // start them right away. But only start so | ||
2046 | // many so we can make some progress on yield | ||
2047 | // queue. | ||
2048 | |||
2049 | int numStarts; | ||
2050 | for (numStarts = 5; -- numStarts >= 0;) | ||
2051 | { | ||
2052 | lock (m_StartQueue) | ||
2053 | { | ||
2054 | inst = m_StartQueue.RemoveHead(); | ||
2055 | } | ||
2056 | if (inst == null) break; | ||
2057 | if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); | ||
2058 | xthd.RunInstance (inst); | ||
2059 | if (m_Exiting || m_SuspendScriptThreadFlag) | ||
2060 | continue; | ||
2061 | } | ||
2062 | |||
2063 | // If there is something to run, run it | ||
2064 | // then rescan from the beginning in case | ||
2065 | // a lot of things have changed meanwhile. | ||
2066 | // | ||
2067 | // These are considered lower priority than | ||
2068 | // m_StartQueue as they have been taking at | ||
2069 | // least one quantum of CPU time and event | ||
2070 | // handlers are supposed to be quick. | ||
2071 | |||
2072 | lock (m_YieldQueue) | ||
2073 | { | ||
2074 | inst = m_YieldQueue.RemoveHead(); | ||
2075 | } | ||
2076 | if (inst != null) | ||
2077 | { | ||
2078 | if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state"); | ||
2079 | xthd.RunInstance(inst); | ||
2080 | numStarts = -1; | ||
2081 | } | ||
2082 | |||
2083 | // If we left something dangling in the m_StartQueue or m_YieldQueue, go back to check it. | ||
2084 | if (m_Exiting || numStarts < 0) | ||
2085 | continue; | ||
2086 | } | ||
2087 | |||
2088 | // Nothing to do, sleep. | ||
2089 | lock (m_WakeUpLock) | ||
2090 | { | ||
2091 | if (!xthd.m_WakeUpThis && (m_WakeUpOne <= 0) && !m_Exiting) | ||
2092 | Monitor.Wait(m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); | ||
2093 | |||
2094 | xthd.m_WakeUpThis = false; | ||
2095 | if ((m_WakeUpOne > 0) && (--m_WakeUpOne > 0)) | ||
2096 | Monitor.Pulse (m_WakeUpLock); | ||
2097 | } | ||
2098 | } | ||
2099 | Watchdog.RemoveThread(true); | ||
1943 | } | 2100 | } |
1944 | } | 2101 | } |
1945 | } | 2102 | } |