aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs262
1 files changed, 262 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs
new file mode 100644
index 0000000..933b478
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs
@@ -0,0 +1,262 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using Mono.Tasklets;
29using OpenSim.Framework.Monitoring;
30using System;
31using System.Collections.Generic;
32using System.Threading;
33
34namespace OpenSim.Region.ScriptEngine.XMREngine
35{
36
37 /**
38 * @brief There are NUMSCRIPTHREADWKRS of these.
39 * Each sits in a loop checking the Start and Yield queues for
40 * a script to run and calls the script as a microthread.
41 */
42 public class XMRScriptThread {
43 private static int m_WakeUpOne = 0;
44 public static object m_WakeUpLock = new object();
45 private static Dictionary<Thread,XMRScriptThread> m_AllThreads = new Dictionary<Thread,XMRScriptThread> ();
46
47 /**
48 * @brief Something was just added to the Start or Yield queue so
49 * wake one of the XMRScriptThread instances to run it.
50 */
51 public static void WakeUpOne()
52 {
53 lock (m_WakeUpLock)
54 {
55 m_WakeUpOne ++;
56 Monitor.Pulse (m_WakeUpLock);
57 }
58 }
59
60 public static XMRScriptThread CurrentScriptThread ()
61 {
62 XMRScriptThread st;
63 lock (m_AllThreads) {
64 m_AllThreads.TryGetValue (Thread.CurrentThread, out st);
65 }
66 return st;
67 }
68
69 private bool m_Exiting = false;
70 private bool m_SuspendScriptThreadFlag = false;
71 private bool m_WakeUpThis = false;
72 private bool m_Continuations = false;
73 public DateTime m_LastRanAt = DateTime.MinValue;
74 public int m_ScriptThreadTID = 0;
75 public long m_ScriptExecTime = 0;
76 private Thread thd;
77 private XMREngine engine;
78 public XMRInstance m_RunInstance = null;
79
80 public XMRScriptThread(XMREngine eng)
81 {
82 engine = eng;
83 m_Continuations = engine.uThreadCtor.DeclaringType == typeof (ScriptUThread_Con);
84 thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.BelowNormal);
85 lock (m_AllThreads) {
86 m_AllThreads.Add (thd, this);
87 }
88 }
89
90 public void SuspendThread()
91 {
92 m_SuspendScriptThreadFlag = true;
93 WakeUpScriptThread();
94 }
95
96 public void ResumeThread()
97 {
98 m_SuspendScriptThreadFlag = false;
99 WakeUpScriptThread();
100 }
101
102 public void Terminate()
103 {
104 m_Exiting = true;
105 WakeUpScriptThread();
106 thd.Join();
107 lock (m_AllThreads) {
108 m_AllThreads.Remove (thd);
109 }
110 thd = null;
111 }
112
113 public void TimeSlice()
114 {
115 XMRInstance instance = m_RunInstance;
116 if (instance != null) {
117 instance.suspendOnCheckRunTemp = true;
118 }
119 }
120
121 /**
122 * @brief Wake up this XMRScriptThread instance.
123 */
124 private void WakeUpScriptThread()
125 {
126 lock (m_WakeUpLock) {
127 m_WakeUpThis = true;
128 Monitor.PulseAll (m_WakeUpLock);
129 }
130 }
131
132 /**
133 * @brief Thread that runs the scripts.
134 */
135 private void RunScriptThread()
136 {
137 XMRInstance inst;
138 Mono.Tasklets.Continuation engstack = null;
139 if (m_Continuations) {
140 engstack = new Mono.Tasklets.Continuation ();
141 engstack.Mark ();
142 }
143 m_ScriptThreadTID = System.Threading.Thread.CurrentThread.ManagedThreadId;
144
145 while (!m_Exiting) {
146 XMREngine.UpdateMyThread ();
147
148 /*
149 * Handle 'xmr resume/suspend' commands.
150 */
151 if (m_SuspendScriptThreadFlag) {
152 lock (m_WakeUpLock) {
153 while (m_SuspendScriptThreadFlag &&
154 !m_Exiting &&
155 (engine.m_ThunkQueue.Count == 0)) {
156 Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2);
157 XMREngine.UpdateMyThread ();
158 }
159 }
160 }
161
162 /*
163 * Maybe there are some scripts waiting to be migrated in or out.
164 */
165 ThreadStart thunk = null;
166 lock (m_WakeUpLock) {
167 if (engine.m_ThunkQueue.Count > 0) {
168 thunk = engine.m_ThunkQueue.Dequeue ();
169 }
170 }
171 if (thunk != null) {
172 inst = (XMRInstance)thunk.Target;
173 if (m_Continuations && (inst.scrstack == null)) {
174 inst.engstack = engstack;
175 inst.scrstack = new Mono.Tasklets.Continuation ();
176 inst.scrstack.Mark ();
177 }
178 thunk ();
179 continue;
180 }
181
182 if (engine.m_StartProcessing) {
183
184 /*
185 * If event just queued to any idle scripts
186 * start them right away. But only start so
187 * many so we can make some progress on yield
188 * queue.
189 */
190 int numStarts;
191 for (numStarts = 5; -- numStarts >= 0;) {
192 lock (engine.m_StartQueue) {
193 inst = engine.m_StartQueue.RemoveHead();
194 }
195 if (inst == null) break;
196 if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state");
197 if (m_Continuations && (inst.scrstack == null)) {
198 inst.engstack = engstack;
199 inst.scrstack = new Mono.Tasklets.Continuation ();
200 inst.scrstack.Mark ();
201 }
202 RunInstance (inst);
203 }
204
205 /*
206 * If there is something to run, run it
207 * then rescan from the beginning in case
208 * a lot of things have changed meanwhile.
209 *
210 * These are considered lower priority than
211 * m_StartQueue as they have been taking at
212 * least one quantum of CPU time and event
213 * handlers are supposed to be quick.
214 */
215 lock (engine.m_YieldQueue) {
216 inst = engine.m_YieldQueue.RemoveHead();
217 }
218 if (inst != null) {
219 if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state");
220 RunInstance (inst);
221 numStarts = -1;
222 }
223
224 /*
225 * If we left something dangling in the m_StartQueue or m_YieldQueue, go back to check it.
226 */
227 if (numStarts < 0) continue;
228 }
229
230 /*
231 * Nothing to do, sleep.
232 */
233 lock (m_WakeUpLock) {
234 if (!m_WakeUpThis && (m_WakeUpOne <= 0) && !m_Exiting) {
235 Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2);
236 }
237 m_WakeUpThis = false;
238 if ((m_WakeUpOne > 0) && (-- m_WakeUpOne > 0)) {
239 Monitor.Pulse (m_WakeUpLock);
240 }
241 }
242 }
243 XMREngine.MyThreadExiting ();
244 }
245
246 /**
247 * @brief A script instance was just removed from the Start or Yield Queue.
248 * So run it for a little bit then stick in whatever queue it should go in.
249 */
250 private void RunInstance (XMRInstance inst)
251 {
252 m_LastRanAt = DateTime.UtcNow;
253 m_ScriptExecTime -= (long)(m_LastRanAt - DateTime.MinValue).TotalMilliseconds;
254 inst.m_IState = XMRInstState.RUNNING;
255 m_RunInstance = inst;
256 XMRInstState newIState = inst.RunOne();
257 m_RunInstance = null;
258 engine.HandleNewIState(inst, newIState);
259 m_ScriptExecTime += (long)(DateTime.UtcNow - DateTime.MinValue).TotalMilliseconds;
260 }
261 }
262}