aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs177
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}