diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
7 files changed, 872 insertions, 1383 deletions
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs b/OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs deleted file mode 100644 index 98910ae..0000000 --- a/OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
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 | |||
28 | // Used to build a dummy Mono.Tasklets.dll file when running on Windows | ||
29 | // Will also work if running with mono, it will just not allow use of | ||
30 | // the "con" and "mmr" thread models, only "sys" will work. | ||
31 | |||
32 | using System; | ||
33 | |||
34 | namespace Mono.Tasklets { | ||
35 | public class Continuation : IDisposable | ||
36 | { | ||
37 | public Continuation () | ||
38 | { | ||
39 | throw new NotSupportedException ("'con' thread model requires mono"); | ||
40 | } | ||
41 | public void Dispose () | ||
42 | { } | ||
43 | |||
44 | public void Mark () | ||
45 | { } | ||
46 | |||
47 | public int Store (int state) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | public void Restore (int state) | ||
53 | { } | ||
54 | } | ||
55 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs index 6b0410a..aa8573c 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs | |||
@@ -25,6 +25,10 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | // based on XMREngine from Mike Rieker (Dreamnation) and Melanie Thielker | ||
29 | // but with several changes to be more cross platform. | ||
30 | |||
31 | |||
28 | using log4net; | 32 | using log4net; |
29 | using Mono.Addins; | 33 | using Mono.Addins; |
30 | using Nini.Config; | 34 | using Nini.Config; |
@@ -37,11 +41,11 @@ using OpenSim.Region.Framework.Scenes; | |||
37 | using OpenSim.Region.ScriptEngine.Interfaces; | 41 | using OpenSim.Region.ScriptEngine.Interfaces; |
38 | using OpenSim.Region.ScriptEngine.Shared; | 42 | using OpenSim.Region.ScriptEngine.Shared; |
39 | using OpenSim.Region.ScriptEngine.Shared.Api; | 43 | using OpenSim.Region.ScriptEngine.Shared.Api; |
40 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | ||
41 | using OpenMetaverse; | 44 | using OpenMetaverse; |
42 | using System; | 45 | using System; |
43 | using System.Collections; | 46 | using System.Collections; |
44 | using System.Collections.Generic; | 47 | using System.Collections.Generic; |
48 | using System.Diagnostics; | ||
45 | using System.IO; | 49 | using System.IO; |
46 | using System.Reflection; | 50 | using System.Reflection; |
47 | using System.Reflection.Emit; | 51 | using System.Reflection.Emit; |
@@ -97,7 +101,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
97 | private int m_HeapSize; | 101 | private int m_HeapSize; |
98 | private XMRScriptThread[] m_ScriptThreads; | 102 | private XMRScriptThread[] m_ScriptThreads; |
99 | private Thread m_SleepThread = null; | 103 | private Thread m_SleepThread = null; |
100 | // private Thread m_SliceThread = null; | ||
101 | private bool m_Exiting = false; | 104 | private bool m_Exiting = false; |
102 | 105 | ||
103 | private int m_MaintenanceInterval = 10; | 106 | private int m_MaintenanceInterval = 10; |
@@ -107,15 +110,14 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
107 | private object m_FrameUpdateLock = new object (); | 110 | private object m_FrameUpdateLock = new object (); |
108 | private event ThreadStart m_FrameUpdateList = null; | 111 | private event ThreadStart m_FrameUpdateList = null; |
109 | 112 | ||
110 | /* | 113 | // Various instance lists: |
111 | * Various instance lists: | 114 | // m_InstancesDict = all known instances |
112 | * m_InstancesDict = all known instances | 115 | // find an instance given its itemID |
113 | * find an instance given its itemID | 116 | // m_StartQueue = instances that have just had event queued to them |
114 | * m_StartQueue = instances that have just had event queued to them | 117 | // m_YieldQueue = instances that are ready to run right now |
115 | * m_YieldQueue = instances that are ready to run right now | 118 | // m_SleepQueue = instances that have m_SleepUntil valid |
116 | * m_SleepQueue = instances that have m_SleepUntil valid | 119 | // sorted by ascending m_SleepUntil |
117 | * sorted by ascending m_SleepUntil | 120 | |
118 | */ | ||
119 | private Dictionary<UUID, XMRInstance> m_InstancesDict = | 121 | private Dictionary<UUID, XMRInstance> m_InstancesDict = |
120 | new Dictionary<UUID, XMRInstance>(); | 122 | new Dictionary<UUID, XMRInstance>(); |
121 | public Queue<ThreadStart> m_ThunkQueue = new Queue<ThreadStart> (); | 123 | public Queue<ThreadStart> m_ThunkQueue = new Queue<ThreadStart> (); |
@@ -126,19 +128,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
126 | 128 | ||
127 | public XMREngine() | 129 | public XMREngine() |
128 | { | 130 | { |
129 | string envar; | ||
130 | |||
131 | envar = Environment.GetEnvironmentVariable ("XMREngineTraceCalls"); | ||
132 | m_TraceCalls = (envar != null) && ((envar[0] & 1) != 0); | ||
133 | m_log.Info ("[XMREngine]: m_TraceCalls=" + m_TraceCalls); | ||
134 | |||
135 | envar = Environment.GetEnvironmentVariable ("XMREngineVerbose"); | ||
136 | m_Verbose = (envar != null) && ((envar[0] & 1) != 0); | ||
137 | m_log.Info ("[XMREngine]: m_Verbose=" + m_Verbose); | ||
138 | |||
139 | envar = Environment.GetEnvironmentVariable ("XMREngineScriptDebug"); | ||
140 | m_ScriptDebug = (envar != null) && ((envar[0] & 1) != 0); | ||
141 | m_log.Info ("[XMREngine]: m_ScriptDebug=" + m_ScriptDebug); | ||
142 | } | 131 | } |
143 | 132 | ||
144 | public string Name | 133 | public string Name |
@@ -190,97 +179,66 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
190 | 179 | ||
191 | m_Enabled = false; | 180 | m_Enabled = false; |
192 | m_Config = config.Configs["XMREngine"]; | 181 | m_Config = config.Configs["XMREngine"]; |
193 | if (m_Config == null) { | 182 | if (m_Config == null) |
183 | { | ||
194 | m_log.Info("[XMREngine]: no config, assuming disabled"); | 184 | m_log.Info("[XMREngine]: no config, assuming disabled"); |
195 | return; | 185 | return; |
196 | } | 186 | } |
187 | |||
197 | m_Enabled = m_Config.GetBoolean("Enabled", false); | 188 | m_Enabled = m_Config.GetBoolean("Enabled", false); |
198 | m_log.InfoFormat("[XMREngine]: config enabled={0}", m_Enabled); | 189 | m_log.InfoFormat("[XMREngine]: config enabled={0}", m_Enabled); |
199 | if (!m_Enabled) { | 190 | if (!m_Enabled) |
200 | return; | 191 | return; |
201 | } | ||
202 | |||
203 | string uThreadModel = "sys"; // will work anywhere | ||
204 | uThreadModel = m_Config.GetString ("UThreadModel", uThreadModel); | ||
205 | 192 | ||
206 | Type uThreadType = null; | 193 | Type uThreadType = null; |
207 | switch (uThreadModel.ToLower ()) { | 194 | uThreadType = typeof (ScriptUThread_Nul); |
208 | |||
209 | // mono continuations - memcpy()s the stack | ||
210 | case "con": { | ||
211 | uThreadType = typeof (ScriptUThread_Con); | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | // patched mono microthreads - switches stack pointer | ||
216 | case "mmr": { | ||
217 | Exception e = ScriptUThread_MMR.LoadMono (); | ||
218 | if (e != null) { | ||
219 | m_log.Error ("[XMREngine]: mmr thread model not available\n", e); | ||
220 | m_Enabled = false; | ||
221 | return; | ||
222 | } | ||
223 | uThreadType = typeof (ScriptUThread_MMR); | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | // system threads - works on mono and windows | ||
228 | case "sys": { | ||
229 | uThreadType = typeof (ScriptUThread_Sys); | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | // who knows what | ||
234 | default: { | ||
235 | m_log.Error ("[XMREngine]: unknown thread model " + uThreadModel); | ||
236 | m_Enabled = false; | ||
237 | return; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | uThreadCtor = uThreadType.GetConstructor (new Type[] { typeof (XMRInstance) }); | 195 | uThreadCtor = uThreadType.GetConstructor (new Type[] { typeof (XMRInstance) }); |
242 | m_log.Info ("[XMREngine]: using thread model " + uThreadModel); | ||
243 | 196 | ||
244 | m_UseSourceHashCode = m_Config.GetBoolean ("UseSourceHashCode", false); | 197 | m_UseSourceHashCode = m_Config.GetBoolean("UseSourceHashCode", false); |
245 | numThreadScriptWorkers = m_Config.GetInt ("NumThreadScriptWorkers", 1); | 198 | numThreadScriptWorkers = m_Config.GetInt("NumThreadScriptWorkers", 3); |
246 | m_ScriptThreads = new XMRScriptThread[numThreadScriptWorkers]; | 199 | m_ScriptThreads = new XMRScriptThread[numThreadScriptWorkers]; |
247 | 200 | ||
248 | for (int i = 0; i < numThreadScriptWorkers; i ++) { | 201 | m_TraceCalls = m_Config.GetBoolean("TraceCalls", false); |
249 | m_ScriptThreads[i] = new XMRScriptThread(this); | 202 | m_Verbose = m_Config.GetBoolean("Verbose", false); |
250 | } | 203 | m_ScriptDebug = m_Config.GetBoolean("ScriptDebug", false); |
251 | 204 | ||
252 | m_SleepThread = StartMyThread (RunSleepThread, "xmrengine sleep", ThreadPriority.Normal); | 205 | // Verify that our ScriptEventCode's match OpenSim's scriptEvent's. |
253 | // m_SliceThread = StartMyThread (RunSliceThread, "xmrengine slice", ThreadPriority.Normal); | ||
254 | |||
255 | /* | ||
256 | * Verify that our ScriptEventCode's match OpenSim's scriptEvent's. | ||
257 | */ | ||
258 | bool err = false; | 206 | bool err = false; |
259 | for (int i = 0; i < 32; i ++) { | 207 | for (int i = 0; i < 32; i ++) |
208 | { | ||
260 | string mycode = "undefined"; | 209 | string mycode = "undefined"; |
261 | string oscode = "undefined"; | 210 | string oscode = "undefined"; |
262 | try { | 211 | try |
212 | { | ||
263 | mycode = ((ScriptEventCode)i).ToString(); | 213 | mycode = ((ScriptEventCode)i).ToString(); |
264 | Convert.ToInt32(mycode); | 214 | Convert.ToInt32(mycode); |
265 | mycode = "undefined"; | 215 | mycode = "undefined"; |
266 | } catch { | ||
267 | } | 216 | } |
268 | try { | 217 | catch { } |
218 | try | ||
219 | { | ||
269 | oscode = ((OpenSim.Region.Framework.Scenes.scriptEvents)(1 << i)).ToString(); | 220 | oscode = ((OpenSim.Region.Framework.Scenes.scriptEvents)(1 << i)).ToString(); |
270 | Convert.ToInt32(oscode); | 221 | Convert.ToInt32(oscode); |
271 | oscode = "undefined"; | 222 | oscode = "undefined"; |
272 | } catch { | ||
273 | } | 223 | } |
274 | if (mycode != oscode) { | 224 | catch { } |
225 | if (mycode != oscode) | ||
226 | { | ||
275 | m_log.ErrorFormat("[XMREngine]: {0} mycode={1}, oscode={2}", i, mycode, oscode); | 227 | m_log.ErrorFormat("[XMREngine]: {0} mycode={1}, oscode={2}", i, mycode, oscode); |
276 | err = true; | 228 | err = true; |
277 | } | 229 | } |
278 | } | 230 | } |
279 | if (err) { | 231 | if (err) |
232 | { | ||
280 | m_Enabled = false; | 233 | m_Enabled = false; |
281 | return; | 234 | return; |
282 | } | 235 | } |
283 | 236 | ||
237 | for (int i = 0; i < numThreadScriptWorkers; i ++) | ||
238 | m_ScriptThreads[i] = new XMRScriptThread(this, i); | ||
239 | |||
240 | m_SleepThread = StartMyThread(RunSleepThread, "xmrengine sleep", ThreadPriority.Normal); | ||
241 | |||
284 | m_StackSize = m_Config.GetInt("ScriptStackSize", 2048) << 10; | 242 | m_StackSize = m_Config.GetInt("ScriptStackSize", 2048) << 10; |
285 | m_HeapSize = m_Config.GetInt("ScriptHeapSize", 1024) << 10; | 243 | m_HeapSize = m_Config.GetInt("ScriptHeapSize", 1024) << 10; |
286 | 244 | ||
@@ -337,12 +295,11 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
337 | 295 | ||
338 | private void OneTimeLateInitialization () | 296 | private void OneTimeLateInitialization () |
339 | { | 297 | { |
340 | /* | 298 | // Build list of defined APIs and their 'this' types and define a field in XMRInstanceSuperType. |
341 | * Build list of defined APIs and their 'this' types and define a field in XMRInstanceSuperType. | ||
342 | */ | ||
343 | ApiManager am = new ApiManager (); | 299 | ApiManager am = new ApiManager (); |
344 | Dictionary<string,Type> apiCtxTypes = new Dictionary<string,Type> (); | 300 | Dictionary<string,Type> apiCtxTypes = new Dictionary<string,Type> (); |
345 | foreach (string api in am.GetApis ()) { | 301 | foreach (string api in am.GetApis ()) |
302 | { | ||
346 | m_log.Debug ("[XMREngine]: adding api " + api); | 303 | m_log.Debug ("[XMREngine]: adding api " + api); |
347 | IScriptApi scriptApi = am.CreateApi (api); | 304 | IScriptApi scriptApi = am.CreateApi (api); |
348 | Type apiCtxType = scriptApi.GetType (); | 305 | Type apiCtxType = scriptApi.GetType (); |
@@ -352,25 +309,36 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
352 | 309 | ||
353 | if (ScriptCodeGen.xmrInstSuperType == null) // Only create type once! | 310 | if (ScriptCodeGen.xmrInstSuperType == null) // Only create type once! |
354 | { | 311 | { |
355 | /* | 312 | // Start creating type XMRInstanceSuperType that contains a field |
356 | * Start creating type XMRInstanceSuperType that contains a field | 313 | // m_ApiManager_<APINAME> that points to the per-instance context |
357 | * m_ApiManager_<APINAME> that points to the per-instance context | 314 | // struct for that API, ie, the 'this' value passed to all methods |
358 | * struct for that API, ie, the 'this' value passed to all methods | 315 | // in that API. It is in essence: |
359 | * in that API. It is in essence: | 316 | |
360 | * | 317 | // public class XMRInstanceSuperType : XMRInstance { |
361 | * public class XMRInstanceSuperType : XMRInstance { | 318 | // public XMRLSL_Api m_ApiManager_LSL; // 'this' value for all ll...() functions |
362 | * public XMRLSL_Api m_ApiManager_LSL; // 'this' value for all ll...() functions | 319 | // public MOD_Api m_ApiManager_MOD; // 'this' value for all mod...() functions |
363 | * public MOD_Api m_ApiManager_MOD; // 'this' value for all mod...() functions | 320 | // public OSSL_Api m_ApiManager_OSSL; // 'this' value for all os...() functions |
364 | * public OSSL_Api m_ApiManager_OSSL; // 'this' value for all os...() functions | 321 | // .... |
365 | * .... | 322 | // } |
366 | * } | 323 | |
367 | */ | ||
368 | AssemblyName assemblyName = new AssemblyName (); | 324 | AssemblyName assemblyName = new AssemblyName (); |
369 | assemblyName.Name = "XMRInstanceSuperAssembly"; | 325 | assemblyName.Name = "XMRInstanceSuperAssembly"; |
370 | AssemblyBuilder assemblyBuilder = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Run); | 326 | AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); |
371 | ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule ("XMRInstanceSuperModule"); | 327 | #if DEBUG |
372 | TypeBuilder typeBuilder = moduleBuilder.DefineType ("XMRInstanceSuperType", TypeAttributes.Public | TypeAttributes.Class); | 328 | Type daType = typeof(DebuggableAttribute); |
373 | typeBuilder.SetParent (typeof (XMRInstance)); | 329 | ConstructorInfo daCtor = daType.GetConstructor(new Type[] { typeof(DebuggableAttribute.DebuggingModes) }); |
330 | |||
331 | CustomAttributeBuilder daBuilder = new CustomAttributeBuilder(daCtor, new object[] { | ||
332 | DebuggableAttribute.DebuggingModes.DisableOptimizations | | ||
333 | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | | ||
334 | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | | ||
335 | DebuggableAttribute.DebuggingModes.Default }); | ||
336 | |||
337 | assemblyBuilder.SetCustomAttribute(daBuilder); | ||
338 | #endif | ||
339 | ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("XMRInstanceSuperModule"); | ||
340 | TypeBuilder typeBuilder = moduleBuilder.DefineType("XMRInstanceSuperType", TypeAttributes.Public | TypeAttributes.Class); | ||
341 | typeBuilder.SetParent(typeof (XMRInstance)); | ||
374 | 342 | ||
375 | foreach (string apiname in apiCtxTypes.Keys) | 343 | foreach (string apiname in apiCtxTypes.Keys) |
376 | { | 344 | { |
@@ -378,23 +346,20 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
378 | typeBuilder.DefineField (fieldName, apiCtxTypes[apiname], FieldAttributes.Public); | 346 | typeBuilder.DefineField (fieldName, apiCtxTypes[apiname], FieldAttributes.Public); |
379 | } | 347 | } |
380 | 348 | ||
381 | /* | 349 | // Finalize definition of XMRInstanceSuperType. |
382 | * Finalize definition of XMRInstanceSuperType. | 350 | // Give the compiler a short name to reference it by, |
383 | * Give the compiler a short name to reference it by, | 351 | // otherwise it will try to use the AssemblyQualifiedName |
384 | * otherwise it will try to use the AssemblyQualifiedName | 352 | // and fail miserably. |
385 | * and fail miserably. | ||
386 | */ | ||
387 | ScriptCodeGen.xmrInstSuperType = typeBuilder.CreateType (); | 353 | ScriptCodeGen.xmrInstSuperType = typeBuilder.CreateType (); |
388 | ScriptObjWriter.DefineInternalType ("xmrsuper", ScriptCodeGen.xmrInstSuperType); | 354 | ScriptObjWriter.DefineInternalType ("xmrsuper", ScriptCodeGen.xmrInstSuperType); |
389 | } | 355 | } |
390 | 356 | ||
391 | /* | 357 | // Tell the compiler about all the constants and methods for each API. |
392 | * Tell the compiler about all the constants and methods for each API. | 358 | // We also tell the compiler how to get the per-instance context for each API |
393 | * We also tell the compiler how to get the per-instance context for each API | 359 | // by reading the corresponding m_ApiManager_<APINAME> field of XMRInstanceSuperType. |
394 | * by reading the corresponding m_ApiManager_<APINAME> field of XMRInstanceSuperType. | ||
395 | */ | ||
396 | foreach (KeyValuePair<string,Type> kvp in apiCtxTypes) { | ||
397 | 360 | ||
361 | foreach (KeyValuePair<string,Type> kvp in apiCtxTypes) | ||
362 | { | ||
398 | // get API name and the corresponding per-instance context type | 363 | // get API name and the corresponding per-instance context type |
399 | string api = kvp.Key; | 364 | string api = kvp.Key; |
400 | Type apiCtxType = kvp.Value; | 365 | Type apiCtxType = kvp.Value; |
@@ -413,41 +378,47 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
413 | TokenDeclInline.AddInterfaceMethods (null, apiCtxType.GetMethods (), fieldInfo); | 378 | TokenDeclInline.AddInterfaceMethods (null, apiCtxType.GetMethods (), fieldInfo); |
414 | } | 379 | } |
415 | 380 | ||
416 | /* | 381 | // Add sim-specific APIs to the compiler. |
417 | * Add sim-specific APIs to the compiler. | ||
418 | */ | ||
419 | IScriptModuleComms comms = m_Scene.RequestModuleInterface<IScriptModuleComms> (); | ||
420 | if (comms != null) { | ||
421 | 382 | ||
422 | /* | 383 | IScriptModuleComms comms = m_Scene.RequestModuleInterface<IScriptModuleComms> (); |
423 | * Add methods to list of built-in functions. | 384 | if (comms != null) |
424 | */ | 385 | { |
386 | // Add methods to list of built-in functions. | ||
425 | Delegate[] methods = comms.GetScriptInvocationList (); | 387 | Delegate[] methods = comms.GetScriptInvocationList (); |
426 | foreach (Delegate m in methods) { | 388 | foreach (Delegate m in methods) |
389 | { | ||
427 | MethodInfo mi = m.Method; | 390 | MethodInfo mi = m.Method; |
428 | try { | 391 | try |
392 | { | ||
429 | CommsCallCodeGen cccg = new CommsCallCodeGen (mi, comms, m_XMRInstanceApiCtxFieldInfos["MOD"]); | 393 | CommsCallCodeGen cccg = new CommsCallCodeGen (mi, comms, m_XMRInstanceApiCtxFieldInfos["MOD"]); |
430 | Verbose ("[XMREngine]: added comms function " + cccg.fullName); | 394 | Verbose ("[XMREngine]: added comms function " + cccg.fullName); |
431 | } catch (Exception e) { | 395 | } |
396 | catch (Exception e) | ||
397 | { | ||
432 | m_log.Error ("[XMREngine]: failed to add comms function " + mi.Name); | 398 | m_log.Error ("[XMREngine]: failed to add comms function " + mi.Name); |
433 | m_log.Error ("[XMREngine]: - " + e.ToString ()); | 399 | m_log.Error ("[XMREngine]: - " + e.ToString ()); |
434 | } | 400 | } |
435 | } | 401 | } |
436 | 402 | ||
437 | /* | 403 | // Add constants to list of built-in constants. |
438 | * Add constants to list of built-in constants. | 404 | |
439 | */ | ||
440 | Dictionary<string,object> consts = comms.GetConstants (); | 405 | Dictionary<string,object> consts = comms.GetConstants (); |
441 | foreach (KeyValuePair<string,object> kvp in consts) { | 406 | foreach (KeyValuePair<string,object> kvp in consts) |
442 | try { | 407 | { |
408 | try | ||
409 | { | ||
443 | ScriptConst sc = ScriptConst.AddConstant (kvp.Key, kvp.Value); | 410 | ScriptConst sc = ScriptConst.AddConstant (kvp.Key, kvp.Value); |
444 | Verbose ("[XMREngine]: added comms constant " + sc.name); | 411 | Verbose ("[XMREngine]: added comms constant " + sc.name); |
445 | } catch (Exception e) { | 412 | } |
413 | catch (Exception e) | ||
414 | { | ||
446 | m_log.Error ("[XMREngine]: failed to add comms constant " + kvp.Key); | 415 | m_log.Error ("[XMREngine]: failed to add comms constant " + kvp.Key); |
447 | m_log.Error ("[XMREngine]: - " + e.Message); | 416 | m_log.Error ("[XMREngine]: - " + e.Message); |
448 | } | 417 | } |
449 | } | 418 | } |
450 | } else { | 419 | } |
420 | else | ||
421 | { | ||
451 | Verbose ("[XMREngine]: comms not enabled"); | 422 | Verbose ("[XMREngine]: comms not enabled"); |
452 | } | 423 | } |
453 | } | 424 | } |
@@ -461,7 +432,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
461 | * do some sick type conversions (with corresponding mallocs) so we can't | 432 | * do some sick type conversions (with corresponding mallocs) so we can't |
462 | * call the methods directly. | 433 | * call the methods directly. |
463 | */ | 434 | */ |
464 | private class CommsCallCodeGen : TokenDeclInline { | 435 | private class CommsCallCodeGen : TokenDeclInline |
436 | { | ||
465 | private static Type[] modInvokerArgTypes = new Type[] { typeof (string), typeof (object[]) }; | 437 | private static Type[] modInvokerArgTypes = new Type[] { typeof (string), typeof (object[]) }; |
466 | public static FieldInfo xmrInstModApiCtxField; | 438 | public static FieldInfo xmrInstModApiCtxField; |
467 | 439 | ||
@@ -492,8 +464,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
492 | { | 464 | { |
493 | methName = mi.Name; | 465 | methName = mi.Name; |
494 | string modInvokerName = comms.LookupModInvocation (methName); | 466 | string modInvokerName = comms.LookupModInvocation (methName); |
495 | if (modInvokerName == null) throw new Exception ("cannot find comms method " + methName); | 467 | if (modInvokerName == null) |
496 | modInvokerMeth = typeof (MOD_Api).GetMethod (modInvokerName, modInvokerArgTypes); | 468 | throw new Exception("cannot find comms method " + methName); |
469 | modInvokerMeth = typeof(MOD_Api).GetMethod(modInvokerName, modInvokerArgTypes); | ||
497 | xmrInstModApiCtxField = apictxfi; | 470 | xmrInstModApiCtxField = apictxfi; |
498 | } | 471 | } |
499 | 472 | ||
@@ -504,7 +477,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
504 | sb.Append (mi.Name); | 477 | sb.Append (mi.Name); |
505 | sb.Append ('('); | 478 | sb.Append ('('); |
506 | ParameterInfo[] mps = mi.GetParameters (); | 479 | ParameterInfo[] mps = mi.GetParameters (); |
507 | for (int i = 2; i < mps.Length; i ++) { | 480 | for (int i = 2; i < mps.Length; i ++) |
481 | { | ||
508 | ParameterInfo pi = mps[i]; | 482 | ParameterInfo pi = mps[i]; |
509 | if (i > 2) sb.Append (','); | 483 | if (i > 2) sb.Append (','); |
510 | sb.Append (ParamType (pi.ParameterType)); | 484 | sb.Append (ParamType (pi.ParameterType)); |
@@ -551,36 +525,31 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
551 | */ | 525 | */ |
552 | public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args) | 526 | public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args) |
553 | { | 527 | { |
554 | /* | 528 | // Set up 'this' pointer for modInvoker?() = value from ApiManager.CreateApi("MOD"). |
555 | * Set up 'this' pointer for modInvoker?() = value from ApiManager.CreateApi("MOD"). | ||
556 | */ | ||
557 | scg.PushXMRInst (); | 529 | scg.PushXMRInst (); |
558 | scg.ilGen.Emit (errorAt, OpCodes.Castclass, xmrInstModApiCtxField.DeclaringType); | 530 | scg.ilGen.Emit (errorAt, OpCodes.Castclass, xmrInstModApiCtxField.DeclaringType); |
559 | scg.ilGen.Emit (errorAt, OpCodes.Ldfld, xmrInstModApiCtxField); | 531 | scg.ilGen.Emit (errorAt, OpCodes.Ldfld, xmrInstModApiCtxField); |
560 | 532 | ||
561 | /* | 533 | // Set up 'fname' argument to modInvoker?() = name of the function to be called. |
562 | * Set up 'fname' argument to modInvoker?() = name of the function to be called. | ||
563 | */ | ||
564 | scg.ilGen.Emit (errorAt, OpCodes.Ldstr, methName); | 534 | scg.ilGen.Emit (errorAt, OpCodes.Ldstr, methName); |
565 | 535 | ||
566 | /* | 536 | // Set up 'parms' argument to modInvoker?() = object[] of the script-visible parameters, |
567 | * Set up 'parms' argument to modInvoker?() = object[] of the script-visible parameters, | 537 | // in their LSL-wrapped form. Of course, the modInvoker?() method will malloc yet another |
568 | * in their LSL-wrapped form. Of course, the modInvoker?() method will malloc yet another | 538 | // object[] and type-convert these parameters one-by-one with another round of unwrapping |
569 | * object[] and type-convert these parameters one-by-one with another round of unwrapping | 539 | // and wrapping. |
570 | * and wrapping. | 540 | // Types allowed in this object[]: |
571 | * Types allowed in this object[]: | 541 | // LSL_Float, LSL_Integer, LSL_Key, LSL_List, LSL_Rotation, LSL_String, LSL_Vector |
572 | * LSL_Float, LSL_Integer, LSL_Key, LSL_List, LSL_Rotation, LSL_String, LSL_Vector | 542 | |
573 | */ | ||
574 | int nargs = args.Length; | 543 | int nargs = args.Length; |
575 | scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4, nargs); | 544 | scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4, nargs); |
576 | scg.ilGen.Emit (errorAt, OpCodes.Newarr, typeof (object)); | 545 | scg.ilGen.Emit (errorAt, OpCodes.Newarr, typeof (object)); |
577 | 546 | ||
578 | for (int i = 0; i < nargs; i ++) { | 547 | for (int i = 0; i < nargs; i ++) |
548 | { | ||
579 | scg.ilGen.Emit (errorAt, OpCodes.Dup); | 549 | scg.ilGen.Emit (errorAt, OpCodes.Dup); |
580 | scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4, i); | 550 | scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4, i); |
581 | 551 | ||
582 | // get location and type of argument | 552 | // get location and type of argument |
583 | |||
584 | CompValu arg = args[i]; | 553 | CompValu arg = args[i]; |
585 | TokenType argtype = arg.type; | 554 | TokenType argtype = arg.type; |
586 | 555 | ||
@@ -593,68 +562,84 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
593 | // then convert to object by boxing if necessary | 562 | // then convert to object by boxing if necessary |
594 | 563 | ||
595 | Type boxit = null; | 564 | Type boxit = null; |
596 | if (argtype is TokenTypeLSLFloat) { | 565 | if (argtype is TokenTypeLSLFloat) |
566 | { | ||
597 | args[i].PushVal (scg, errorAt); | 567 | args[i].PushVal (scg, errorAt); |
598 | boxit = typeof (LSL_Float); | 568 | boxit = typeof (LSL_Float); |
599 | } else if (argtype is TokenTypeLSLInt) { | 569 | } |
570 | else if (argtype is TokenTypeLSLInt) | ||
571 | { | ||
600 | args[i].PushVal (scg, errorAt); | 572 | args[i].PushVal (scg, errorAt); |
601 | boxit = typeof (LSL_Integer); | 573 | boxit = typeof (LSL_Integer); |
602 | } else if (argtype is TokenTypeLSLKey) { | 574 | } |
575 | else if (argtype is TokenTypeLSLKey) | ||
576 | { | ||
603 | args[i].PushVal (scg, errorAt); | 577 | args[i].PushVal (scg, errorAt); |
604 | boxit = typeof (LSL_Key); | 578 | boxit = typeof (LSL_Key); |
605 | } else if (argtype is TokenTypeList) { | 579 | } |
580 | else if (argtype is TokenTypeList) | ||
581 | { | ||
606 | args[i].PushVal (scg, errorAt); | 582 | args[i].PushVal (scg, errorAt); |
607 | boxit = typeof (LSL_List); | 583 | boxit = typeof (LSL_List); |
608 | } else if (argtype is TokenTypeRot) { | 584 | } |
585 | else if (argtype is TokenTypeRot) | ||
586 | { | ||
609 | args[i].PushVal (scg, errorAt); | 587 | args[i].PushVal (scg, errorAt); |
610 | boxit = typeof (LSL_Rotation); | 588 | boxit = typeof (LSL_Rotation); |
611 | } else if (argtype is TokenTypeLSLString) { | 589 | } |
590 | else if (argtype is TokenTypeLSLString) | ||
591 | { | ||
612 | args[i].PushVal (scg, errorAt); | 592 | args[i].PushVal (scg, errorAt); |
613 | boxit = typeof (LSL_String); | 593 | boxit = typeof (LSL_String); |
614 | } else if (argtype is TokenTypeVec) { | 594 | } |
595 | else if (argtype is TokenTypeVec) | ||
596 | { | ||
615 | args[i].PushVal (scg, errorAt); | 597 | args[i].PushVal (scg, errorAt); |
616 | boxit = typeof (LSL_Vector); | 598 | boxit = typeof (LSL_Vector); |
617 | } else if (argtype is TokenTypeFloat) { | 599 | } |
600 | else if (argtype is TokenTypeFloat) | ||
601 | { | ||
618 | args[i].PushVal (scg, errorAt, new TokenTypeLSLFloat (argtype)); | 602 | args[i].PushVal (scg, errorAt, new TokenTypeLSLFloat (argtype)); |
619 | boxit = typeof (LSL_Float); | 603 | boxit = typeof (LSL_Float); |
620 | } else if (argtype is TokenTypeInt) { | 604 | } |
605 | else if (argtype is TokenTypeInt) | ||
606 | { | ||
621 | args[i].PushVal (scg, errorAt, new TokenTypeLSLInt (argtype)); | 607 | args[i].PushVal (scg, errorAt, new TokenTypeLSLInt (argtype)); |
622 | boxit = typeof (LSL_Integer); | 608 | boxit = typeof (LSL_Integer); |
623 | } else if (argtype is TokenTypeKey) { | 609 | } |
610 | else if (argtype is TokenTypeKey) | ||
611 | { | ||
624 | args[i].PushVal (scg, errorAt, new TokenTypeLSLKey (argtype)); | 612 | args[i].PushVal (scg, errorAt, new TokenTypeLSLKey (argtype)); |
625 | boxit = typeof (LSL_Key); | 613 | boxit = typeof (LSL_Key); |
626 | } else if (argtype is TokenTypeStr) { | 614 | } |
615 | else if (argtype is TokenTypeStr) | ||
616 | { | ||
627 | args[i].PushVal (scg, errorAt, new TokenTypeLSLString (argtype)); | 617 | args[i].PushVal (scg, errorAt, new TokenTypeLSLString (argtype)); |
628 | boxit = typeof (LSL_String); | 618 | boxit = typeof (LSL_String); |
629 | } else { | ||
630 | throw new Exception ("unsupported arg type " + argtype.GetType ().Name); | ||
631 | } | 619 | } |
632 | if (boxit.IsValueType) { | 620 | else |
621 | throw new Exception ("unsupported arg type " + argtype.GetType ().Name); | ||
622 | |||
623 | if (boxit.IsValueType) | ||
633 | scg.ilGen.Emit (errorAt, OpCodes.Box, boxit); | 624 | scg.ilGen.Emit (errorAt, OpCodes.Box, boxit); |
634 | } | ||
635 | 625 | ||
636 | // pop the object into the object[] | 626 | // pop the object into the object[] |
637 | |||
638 | scg.ilGen.Emit (errorAt, OpCodes.Stelem, typeof (object)); | 627 | scg.ilGen.Emit (errorAt, OpCodes.Stelem, typeof (object)); |
639 | } | 628 | } |
640 | 629 | ||
641 | /* | 630 | // Call the modInvoker?() method. |
642 | * Call the modInvoker?() method. | 631 | // It leaves an LSL-wrapped type on the stack. |
643 | * It leaves an LSL-wrapped type on the stack. | 632 | if (modInvokerMeth.IsVirtual) |
644 | */ | ||
645 | if (modInvokerMeth.IsVirtual) { | ||
646 | scg.ilGen.Emit (errorAt, OpCodes.Callvirt, modInvokerMeth); | 633 | scg.ilGen.Emit (errorAt, OpCodes.Callvirt, modInvokerMeth); |
647 | } else { | 634 | else |
648 | scg.ilGen.Emit (errorAt, OpCodes.Call, modInvokerMeth); | 635 | scg.ilGen.Emit (errorAt, OpCodes.Call, modInvokerMeth); |
649 | } | ||
650 | 636 | ||
651 | /* | 637 | // The 3rd arg to Pop() is the type on the stack, |
652 | * The 3rd arg to Pop() is the type on the stack, | 638 | // ie, what modInvoker?() actually returns. |
653 | * ie, what modInvoker?() actually returns. | 639 | // The Pop() method will wrap/unwrap as needed. |
654 | * The Pop() method will wrap/unwrap as needed. | ||
655 | */ | ||
656 | Type retSysType = modInvokerMeth.ReturnType; | 640 | Type retSysType = modInvokerMeth.ReturnType; |
657 | if (retSysType == null) retSysType = typeof (void); | 641 | if (retSysType == null) |
642 | retSysType = typeof (void); | ||
658 | TokenType retTokType = TokenType.FromSysType (errorAt, retSysType); | 643 | TokenType retTokType = TokenType.FromSysType (errorAt, retSysType); |
659 | result.Pop (scg, errorAt, retTokType); | 644 | result.Pop (scg, errorAt, retTokType); |
660 | } | 645 | } |
@@ -671,17 +656,23 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
671 | 656 | ||
672 | TraceCalls("[XMREngine]: XMREngine.RemoveRegion({0})", scene.RegionInfo.RegionName); | 657 | TraceCalls("[XMREngine]: XMREngine.RemoveRegion({0})", scene.RegionInfo.RegionName); |
673 | 658 | ||
674 | /* | 659 | // Write script states out to .state files so it will be |
675 | * Write script states out to .state files so it will be | 660 | // available when the region is restarted. |
676 | * available when the region is restarted. | ||
677 | */ | ||
678 | DoMaintenance(null, null); | 661 | DoMaintenance(null, null); |
679 | 662 | ||
680 | /* | 663 | // Stop executing script threads and wait for final |
681 | * Stop executing script threads and wait for final | 664 | // one to finish (ie, script gets to CheckRun() call). |
682 | * one to finish (ie, script gets to CheckRun() call). | ||
683 | */ | ||
684 | m_Exiting = true; | 665 | m_Exiting = true; |
666 | |||
667 | m_Scene.EventManager.OnFrame -= OnFrame; | ||
668 | m_Scene.EventManager.OnRezScript -= OnRezScript; | ||
669 | m_Scene.EventManager.OnRemoveScript -= OnRemoveScript; | ||
670 | m_Scene.EventManager.OnScriptReset -= OnScriptReset; | ||
671 | m_Scene.EventManager.OnStartScript -= OnStartScript; | ||
672 | m_Scene.EventManager.OnStopScript -= OnStopScript; | ||
673 | m_Scene.EventManager.OnGetScriptRunning -= OnGetScriptRunning; | ||
674 | m_Scene.EventManager.OnShutdown -= OnShutdown; | ||
675 | |||
685 | for (int i = 0; i < numThreadScriptWorkers; i ++) | 676 | for (int i = 0; i < numThreadScriptWorkers; i ++) |
686 | { | 677 | { |
687 | XMRScriptThread scriptThread = m_ScriptThreads[i]; | 678 | XMRScriptThread scriptThread = m_ScriptThreads[i]; |
@@ -702,21 +693,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
702 | m_SleepThread.Abort(); | 693 | m_SleepThread.Abort(); |
703 | m_SleepThread = null; | 694 | m_SleepThread = null; |
704 | } | 695 | } |
705 | /* | ||
706 | if (m_SliceThread != null) | ||
707 | { | ||
708 | m_SliceThread.Join(); | ||
709 | m_SliceThread = null; | ||
710 | } | ||
711 | */ | ||
712 | m_Scene.EventManager.OnFrame -= OnFrame; | ||
713 | m_Scene.EventManager.OnRezScript -= OnRezScript; | ||
714 | m_Scene.EventManager.OnRemoveScript -= OnRemoveScript; | ||
715 | m_Scene.EventManager.OnScriptReset -= OnScriptReset; | ||
716 | m_Scene.EventManager.OnStartScript -= OnStartScript; | ||
717 | m_Scene.EventManager.OnStopScript -= OnStopScript; | ||
718 | m_Scene.EventManager.OnGetScriptRunning -= OnGetScriptRunning; | ||
719 | m_Scene.EventManager.OnShutdown -= OnShutdown; | ||
720 | 696 | ||
721 | m_Enabled = false; | 697 | m_Enabled = false; |
722 | m_Scene = null; | 698 | m_Scene = null; |
@@ -758,46 +734,51 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
758 | 734 | ||
759 | private void RunTest (string module, string[] args) | 735 | private void RunTest (string module, string[] args) |
760 | { | 736 | { |
761 | if (args.Length < 2) { | 737 | if (args.Length < 2) |
738 | { | ||
762 | m_log.Info ("[XMREngine]: missing command, try 'xmr help'"); | 739 | m_log.Info ("[XMREngine]: missing command, try 'xmr help'"); |
763 | return; | 740 | return; |
764 | } | 741 | } |
765 | 742 | ||
766 | switch (args[1]) { | 743 | switch (args[1]) |
767 | case "cvv": { | 744 | { |
768 | switch (args.Length) { | 745 | case "cvv": |
769 | case 2: { | 746 | switch (args.Length) |
747 | { | ||
748 | case 2: | ||
770 | m_log.InfoFormat ("[XMREngine]: compiled version value = {0}", | 749 | m_log.InfoFormat ("[XMREngine]: compiled version value = {0}", |
771 | ScriptCodeGen.COMPILED_VERSION_VALUE); | 750 | ScriptCodeGen.COMPILED_VERSION_VALUE); |
772 | break; | 751 | break; |
773 | } | 752 | |
774 | case 3: { | 753 | case 3: |
775 | try { | 754 | try |
755 | { | ||
776 | ScriptCodeGen.COMPILED_VERSION_VALUE = Convert.ToInt32 (args[2]); | 756 | ScriptCodeGen.COMPILED_VERSION_VALUE = Convert.ToInt32 (args[2]); |
777 | } catch { | 757 | } |
758 | catch | ||
759 | { | ||
778 | m_log.Error ("[XMREngine]: bad/missing version number"); | 760 | m_log.Error ("[XMREngine]: bad/missing version number"); |
779 | } | 761 | } |
780 | break; | 762 | break; |
781 | } | 763 | |
782 | default: { | 764 | default: |
783 | m_log.Error ("[XMREngine]: xmr cvv [<new_compiled_version_value>]"); | 765 | m_log.Error ("[XMREngine]: xmr cvv [<new_compiled_version_value>]"); |
784 | break; | 766 | break; |
785 | } | ||
786 | } | 767 | } |
787 | break; | 768 | break; |
788 | } | 769 | |
789 | case "echo": { | 770 | case "echo": |
790 | for (int i = 0; i < args.Length; i ++) { | 771 | for (int i = 0; i < args.Length; i ++) |
791 | m_log.Info ("[XMREngine]: echo[" + i + "]=<" + args[i] + ">"); | 772 | m_log.Info ("[XMREngine]: echo[" + i + "]=<" + args[i] + ">"); |
792 | } | 773 | |
793 | break; | 774 | break; |
794 | } | 775 | |
795 | case "gc": { | 776 | case "gc": |
796 | GC.Collect(); | 777 | GC.Collect(); |
797 | break; | 778 | break; |
798 | } | 779 | |
799 | case "help": | 780 | case "help": |
800 | case "?": { | 781 | case "?": |
801 | m_log.Info ("[XMREngine]: xmr cvv [<newvalue>] - show/set compiled version value"); | 782 | m_log.Info ("[XMREngine]: xmr cvv [<newvalue>] - show/set compiled version value"); |
802 | m_log.Info ("[XMREngine]: xmr gc"); | 783 | m_log.Info ("[XMREngine]: xmr gc"); |
803 | m_log.Info ("[XMREngine]: xmr ls [-help ...]"); | 784 | m_log.Info ("[XMREngine]: xmr ls [-help ...]"); |
@@ -809,75 +790,74 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
809 | m_log.Info ("[XMREngine]: xmr tracecalls [yes | no]"); | 790 | m_log.Info ("[XMREngine]: xmr tracecalls [yes | no]"); |
810 | m_log.Info ("[XMREngine]: xmr verbose [yes | no]"); | 791 | m_log.Info ("[XMREngine]: xmr verbose [yes | no]"); |
811 | break; | 792 | break; |
812 | } | 793 | |
813 | case "ls": { | 794 | case "ls": |
814 | XmrTestLs (args, 2); | 795 | XmrTestLs (args, 2); |
815 | break; | 796 | break; |
816 | } | 797 | |
817 | case "mvv": { | 798 | case "mvv": |
818 | switch (args.Length) { | 799 | switch (args.Length) |
819 | case 2: { | 800 | { |
801 | case 2: | ||
820 | m_log.InfoFormat ("[XMREngine]: migration version value = {0}", | 802 | m_log.InfoFormat ("[XMREngine]: migration version value = {0}", |
821 | XMRInstance.migrationVersion); | 803 | XMRInstance.migrationVersion); |
822 | break; | 804 | break; |
823 | } | 805 | |
824 | case 3: { | 806 | case 3: |
825 | try { | 807 | try |
808 | { | ||
826 | int mvv = Convert.ToInt32 (args[2]); | 809 | int mvv = Convert.ToInt32 (args[2]); |
827 | if ((mvv < 0) || (mvv > 255)) throw new Exception ("out of range"); | 810 | if ((mvv < 0) || (mvv > 255)) throw new Exception ("out of range"); |
828 | XMRInstance.migrationVersion = (byte) mvv; | 811 | XMRInstance.migrationVersion = (byte) mvv; |
829 | } catch (Exception e) { | 812 | } |
813 | catch (Exception e) | ||
814 | { | ||
830 | m_log.Error ("[XMREngine]: bad/missing version number (" + e.Message + ")"); | 815 | m_log.Error ("[XMREngine]: bad/missing version number (" + e.Message + ")"); |
831 | } | 816 | } |
832 | break; | 817 | break; |
833 | } | 818 | |
834 | default: { | 819 | default: |
835 | m_log.Error ("[XMREngine]: xmr mvv [<new_migration_version_value>]"); | 820 | m_log.Error ("[XMREngine]: xmr mvv [<new_migration_version_value>]"); |
836 | break; | 821 | break; |
837 | } | ||
838 | } | 822 | } |
839 | break; | 823 | break; |
840 | } | 824 | |
841 | case "pev": { | 825 | case "pev": |
842 | XmrTestPev (args, 2); | 826 | XmrTestPev (args, 2); |
843 | break; | 827 | break; |
844 | } | 828 | |
845 | case "reset": { | 829 | case "reset": |
846 | XmrTestReset (args, 2); | 830 | XmrTestReset (args, 2); |
847 | break; | 831 | break; |
848 | } | 832 | |
849 | case "resume": { | 833 | case "resume": |
850 | m_log.Info ("[XMREngine]: resuming scripts"); | 834 | m_log.Info ("[XMREngine]: resuming scripts"); |
851 | for (int i = 0; i < numThreadScriptWorkers; i ++) { | 835 | for (int i = 0; i < numThreadScriptWorkers; i ++) |
852 | m_ScriptThreads[i].ResumeThread(); | 836 | m_ScriptThreads[i].ResumeThread(); |
853 | } | 837 | |
854 | break; | 838 | break; |
855 | } | 839 | |
856 | case "suspend": { | 840 | case "suspend": |
857 | m_log.Info ("[XMREngine]: suspending scripts"); | 841 | m_log.Info ("[XMREngine]: suspending scripts"); |
858 | for (int i = 0; i < numThreadScriptWorkers; i ++) { | 842 | for (int i = 0; i < numThreadScriptWorkers; i ++) |
859 | m_ScriptThreads[i].SuspendThread(); | 843 | m_ScriptThreads[i].SuspendThread(); |
860 | } | ||
861 | break; | 844 | break; |
862 | } | 845 | |
863 | case "tracecalls": { | 846 | case "tracecalls": |
864 | if (args.Length > 2) { | 847 | if (args.Length > 2) |
865 | m_TraceCalls = (args[2][0] & 1) != 0; | 848 | m_TraceCalls = (args[2][0] & 1) != 0; |
866 | } | ||
867 | m_log.Info ("[XMREngine]: tracecalls " + (m_TraceCalls ? "yes" : "no")); | 849 | m_log.Info ("[XMREngine]: tracecalls " + (m_TraceCalls ? "yes" : "no")); |
868 | break; | 850 | break; |
869 | } | 851 | |
870 | case "verbose": { | 852 | case "verbose": |
871 | if (args.Length > 2) { | 853 | if (args.Length > 2) |
872 | m_Verbose = (args[2][0] & 1) != 0; | 854 | m_Verbose = (args[2][0] & 1) != 0; |
873 | } | ||
874 | m_log.Info ("[XMREngine]: verbose " + (m_Verbose ? "yes" : "no")); | 855 | m_log.Info ("[XMREngine]: verbose " + (m_Verbose ? "yes" : "no")); |
875 | break; | 856 | break; |
876 | } | 857 | |
877 | default: { | 858 | default: |
878 | m_log.Error ("[XMREngine]: unknown command " + args[1] + ", try 'xmr help'"); | 859 | m_log.Error ("[XMREngine]: unknown command " + args[1] + ", try 'xmr help'"); |
879 | break; | 860 | break; |
880 | } | ||
881 | } | 861 | } |
882 | } | 862 | } |
883 | 863 | ||
@@ -935,23 +915,21 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
935 | 915 | ||
936 | TraceCalls("[XMREngine]: XMREngine.PostObjectEvent({0},{1})", localID.ToString(), parms.EventName); | 916 | TraceCalls("[XMREngine]: XMREngine.PostObjectEvent({0},{1})", localID.ToString(), parms.EventName); |
937 | 917 | ||
938 | /* | 918 | // In SecondLife, attach events go to all scripts of all prims |
939 | * In SecondLife, attach events go to all scripts of all prims | 919 | // in a linked object. So here we duplicate that functionality, |
940 | * in a linked object. So here we duplicate that functionality, | 920 | // as all we ever get is a single attach event for the whole |
941 | * as all we ever get is a single attach event for the whole | 921 | // object. |
942 | * object. | 922 | if (parms.EventName == "attach") |
943 | */ | 923 | { |
944 | if (parms.EventName == "attach") { | ||
945 | bool posted = false; | 924 | bool posted = false; |
946 | foreach (SceneObjectPart primpart in part.ParentGroup.Parts) { | 925 | foreach (SceneObjectPart primpart in part.ParentGroup.Parts) |
926 | { | ||
947 | posted |= PostPrimEvent (primpart, parms); | 927 | posted |= PostPrimEvent (primpart, parms); |
948 | } | 928 | } |
949 | return posted; | 929 | return posted; |
950 | } | 930 | } |
951 | 931 | ||
952 | /* | 932 | // Other events go to just the scripts in that prim. |
953 | * Other events go to just the scripts in that prim. | ||
954 | */ | ||
955 | return PostPrimEvent (part, parms); | 933 | return PostPrimEvent (part, parms); |
956 | } | 934 | } |
957 | 935 | ||
@@ -959,34 +937,33 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
959 | { | 937 | { |
960 | UUID partUUID = part.UUID; | 938 | UUID partUUID = part.UUID; |
961 | 939 | ||
962 | /* | 940 | // Get list of script instances running in the object. |
963 | * Get list of script instances running in the object. | ||
964 | */ | ||
965 | XMRInstance[] objInstArray; | 941 | XMRInstance[] objInstArray; |
966 | lock (m_InstancesDict) { | 942 | lock (m_InstancesDict) |
967 | if (!m_ObjectInstArray.TryGetValue (partUUID, out objInstArray)) { | 943 | { |
944 | if (!m_ObjectInstArray.TryGetValue (partUUID, out objInstArray)) | ||
968 | return false; | 945 | return false; |
969 | } | 946 | |
970 | if (objInstArray == null) { | 947 | if (objInstArray == null) |
948 | { | ||
971 | objInstArray = RebuildObjectInstArray (partUUID); | 949 | objInstArray = RebuildObjectInstArray (partUUID); |
972 | m_ObjectInstArray[partUUID] = objInstArray; | 950 | m_ObjectInstArray[partUUID] = objInstArray; |
973 | } | 951 | } |
974 | } | 952 | } |
975 | 953 | ||
976 | /* | 954 | // Post event to all script instances in the object. |
977 | * Post event to all script instances in the object. | ||
978 | */ | ||
979 | if (objInstArray.Length <= 0) return false; | 955 | if (objInstArray.Length <= 0) return false; |
980 | foreach (XMRInstance inst in objInstArray) { | 956 | foreach (XMRInstance inst in objInstArray) |
981 | inst.PostEvent (parms); | 957 | inst.PostEvent (parms); |
982 | } | 958 | |
983 | return true; | 959 | return true; |
984 | } | 960 | } |
985 | 961 | ||
986 | public DetectParams GetDetectParams(UUID itemID, int number) | 962 | public DetectParams GetDetectParams(UUID itemID, int number) |
987 | { | 963 | { |
988 | XMRInstance instance = GetInstance (itemID); | 964 | XMRInstance instance = GetInstance (itemID); |
989 | if (instance == null) return null; | 965 | if (instance == null) |
966 | return null; | ||
990 | return instance.GetDetectParams(number); | 967 | return instance.GetDetectParams(number); |
991 | } | 968 | } |
992 | 969 | ||
@@ -997,7 +974,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
997 | public int GetStartParameter(UUID itemID) | 974 | public int GetStartParameter(UUID itemID) |
998 | { | 975 | { |
999 | XMRInstance instance = GetInstance (itemID); | 976 | XMRInstance instance = GetInstance (itemID); |
1000 | if (instance == null) return 0; | 977 | if (instance == null) |
978 | return 0; | ||
1001 | return instance.StartParam; | 979 | return instance.StartParam; |
1002 | } | 980 | } |
1003 | 981 | ||
@@ -1010,9 +988,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1010 | public void SetScriptState(UUID itemID, bool state) | 988 | public void SetScriptState(UUID itemID, bool state) |
1011 | { | 989 | { |
1012 | XMRInstance instance = GetInstance (itemID); | 990 | XMRInstance instance = GetInstance (itemID); |
1013 | if (instance != null) { | 991 | if (instance != null) |
1014 | instance.Running = state; | 992 | instance.Running = state; |
1015 | } | ||
1016 | } | 993 | } |
1017 | 994 | ||
1018 | // Control display of the "running" checkbox | 995 | // Control display of the "running" checkbox |
@@ -1020,7 +997,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1020 | public bool GetScriptState(UUID itemID) | 997 | public bool GetScriptState(UUID itemID) |
1021 | { | 998 | { |
1022 | XMRInstance instance = GetInstance (itemID); | 999 | XMRInstance instance = GetInstance (itemID); |
1023 | if (instance == null) return false; | 1000 | if (instance == null) |
1001 | return false; | ||
1024 | return instance.Running; | 1002 | return instance.Running; |
1025 | } | 1003 | } |
1026 | 1004 | ||
@@ -1032,15 +1010,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1032 | public void ApiResetScript(UUID itemID) | 1010 | public void ApiResetScript(UUID itemID) |
1033 | { | 1011 | { |
1034 | XMRInstance instance = GetInstance (itemID); | 1012 | XMRInstance instance = GetInstance (itemID); |
1035 | if (instance != null) { | 1013 | if (instance != null) |
1036 | instance.ApiReset(); | 1014 | instance.ApiReset(); |
1037 | } | ||
1038 | } | 1015 | } |
1039 | 1016 | ||
1040 | public void ResetScript(UUID itemID) | 1017 | public void ResetScript(UUID itemID) |
1041 | { | 1018 | { |
1042 | XMRInstance instance = GetInstance (itemID); | 1019 | XMRInstance instance = GetInstance (itemID); |
1043 | if (instance != null) { | 1020 | if (instance != null) |
1021 | { | ||
1044 | IUrlModule urlModule = m_Scene.RequestModuleInterface<IUrlModule>(); | 1022 | IUrlModule urlModule = m_Scene.RequestModuleInterface<IUrlModule>(); |
1045 | if (urlModule != null) | 1023 | if (urlModule != null) |
1046 | urlModule.ScriptRemoved(itemID); | 1024 | urlModule.ScriptRemoved(itemID); |
@@ -1067,7 +1045,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1067 | public IScriptApi GetApi(UUID itemID, string name) | 1045 | public IScriptApi GetApi(UUID itemID, string name) |
1068 | { | 1046 | { |
1069 | FieldInfo fi; | 1047 | FieldInfo fi; |
1070 | if (!m_XMRInstanceApiCtxFieldInfos.TryGetValue (name, out fi)) return null; | 1048 | if (!m_XMRInstanceApiCtxFieldInfos.TryGetValue (name, out fi)) |
1049 | return null; | ||
1071 | XMRInstance inst = GetInstance (itemID); | 1050 | XMRInstance inst = GetInstance (itemID); |
1072 | if (inst == null) return null; | 1051 | if (inst == null) return null; |
1073 | return (IScriptApi)fi.GetValue (inst); | 1052 | return (IScriptApi)fi.GetValue (inst); |
@@ -1081,11 +1060,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1081 | public string GetXMLState(UUID itemID) | 1060 | public string GetXMLState(UUID itemID) |
1082 | { | 1061 | { |
1083 | XMRInstance instance = GetInstance (itemID); | 1062 | XMRInstance instance = GetInstance (itemID); |
1084 | if (instance == null) return String.Empty; | 1063 | if (instance == null) |
1064 | return String.Empty; | ||
1085 | 1065 | ||
1086 | TraceCalls("[XMREngine]: XMREngine.GetXMLState({0})", itemID.ToString()); | 1066 | TraceCalls("[XMREngine]: XMREngine.GetXMLState({0})", itemID.ToString()); |
1087 | 1067 | ||
1088 | if (!instance.m_HasRun) return String.Empty; | 1068 | if (!instance.m_HasRun) |
1069 | return String.Empty; | ||
1089 | 1070 | ||
1090 | XmlDocument doc = new XmlDocument(); | 1071 | XmlDocument doc = new XmlDocument(); |
1091 | 1072 | ||
@@ -1108,10 +1089,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1108 | assetA.Value = assetID; | 1089 | assetA.Value = assetID; |
1109 | stateN.Attributes.Append(assetA); | 1090 | stateN.Attributes.Append(assetA); |
1110 | 1091 | ||
1111 | /* | 1092 | // Get <ScriptState>...</ScriptState> item that hold's script's state. |
1112 | * Get <ScriptState>...</ScriptState> item that hold's script's state. | 1093 | // This suspends the script if necessary then takes a snapshot. |
1113 | * This suspends the script if necessary then takes a snapshot. | ||
1114 | */ | ||
1115 | XmlElement scriptStateN = instance.GetExecutionState(doc); | 1094 | XmlElement scriptStateN = instance.GetExecutionState(doc); |
1116 | stateN.AppendChild(scriptStateN); | 1095 | stateN.AppendChild(scriptStateN); |
1117 | 1096 | ||
@@ -1147,13 +1126,12 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1147 | 1126 | ||
1148 | // <ScriptState>...</ScriptState> contains contents of .state file. | 1127 | // <ScriptState>...</ScriptState> contains contents of .state file. |
1149 | XmlElement scriptStateN = (XmlElement)stateN.SelectSingleNode("ScriptState"); | 1128 | XmlElement scriptStateN = (XmlElement)stateN.SelectSingleNode("ScriptState"); |
1150 | if (scriptStateN == null) { | 1129 | if (scriptStateN == null) |
1151 | return false; | 1130 | return false; |
1152 | } | 1131 | |
1153 | string sen = stateN.GetAttribute("Engine"); | 1132 | string sen = stateN.GetAttribute("Engine"); |
1154 | if ((sen == null) || (sen != ScriptEngineName)) { | 1133 | if ((sen == null) || (sen != ScriptEngineName)) |
1155 | return false; | 1134 | return false; |
1156 | } | ||
1157 | 1135 | ||
1158 | XmlAttribute assetA = doc.CreateAttribute("", "Asset", ""); | 1136 | XmlAttribute assetA = doc.CreateAttribute("", "Asset", ""); |
1159 | assetA.Value = stateN.GetAttribute("Asset"); | 1137 | assetA.Value = stateN.GetAttribute("Asset"); |
@@ -1198,9 +1176,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1198 | public void SleepScript(UUID itemID, int delay) | 1176 | public void SleepScript(UUID itemID, int delay) |
1199 | { | 1177 | { |
1200 | XMRInstance instance = GetInstance (itemID); | 1178 | XMRInstance instance = GetInstance (itemID); |
1201 | if (instance != null) { | 1179 | if (instance != null) |
1202 | instance.Sleep (delay); | 1180 | instance.Sleep (delay); |
1203 | } | ||
1204 | } | 1181 | } |
1205 | 1182 | ||
1206 | // Get a script instance loaded, compiling it if necessary | 1183 | // Get a script instance loaded, compiling it if necessary |
@@ -1219,21 +1196,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1219 | SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); | 1196 | SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); |
1220 | TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID); | 1197 | TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID); |
1221 | 1198 | ||
1222 | if (!m_LateInit) { | 1199 | if (!m_LateInit) |
1200 | { | ||
1223 | m_LateInit = true; | 1201 | m_LateInit = true; |
1224 | OneTimeLateInitialization (); | 1202 | OneTimeLateInitialization (); |
1225 | } | 1203 | } |
1226 | 1204 | ||
1227 | TraceCalls("[XMREngine]: OnRezScript(...,{0},...)", itemID.ToString()); | 1205 | TraceCalls("[XMREngine]: OnRezScript(...,{0},...)", itemID.ToString()); |
1228 | 1206 | ||
1229 | /* | 1207 | // Assume script uses the default engine, whatever that is. |
1230 | * Assume script uses the default engine, whatever that is. | ||
1231 | */ | ||
1232 | string engineName = defEngine; | 1208 | string engineName = defEngine; |
1233 | 1209 | ||
1234 | /* | 1210 | // Very first line might contain "//" scriptengine ":". |
1235 | * Very first line might contain "//" scriptengine ":". | ||
1236 | */ | ||
1237 | string firstline = ""; | 1211 | string firstline = ""; |
1238 | if (script.StartsWith("//")) { | 1212 | if (script.StartsWith("//")) { |
1239 | int lineEnd = script.IndexOf('\n'); | 1213 | int lineEnd = script.IndexOf('\n'); |
@@ -1245,39 +1219,32 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1245 | } | 1219 | } |
1246 | } | 1220 | } |
1247 | 1221 | ||
1248 | /* | 1222 | // Make sure the default or requested engine is us. |
1249 | * Make sure the default or requested engine is us. | ||
1250 | */ | ||
1251 | if (engineName != ScriptEngineName) { | 1223 | if (engineName != ScriptEngineName) { |
1252 | 1224 | ||
1253 | /* | 1225 | // Not us, if requested engine exists, silently ignore script and let |
1254 | * Not us, if requested engine exists, silently ignore script and let | 1226 | // requested engine handle it. |
1255 | * requested engine handle it. | ||
1256 | */ | ||
1257 | IScriptModule[] engines = m_Scene.RequestModuleInterfaces<IScriptModule> (); | 1227 | IScriptModule[] engines = m_Scene.RequestModuleInterfaces<IScriptModule> (); |
1258 | foreach (IScriptModule eng in engines) { | 1228 | foreach (IScriptModule eng in engines) |
1259 | if (eng.ScriptEngineName == engineName) { | 1229 | { |
1230 | if (eng.ScriptEngineName == engineName) | ||
1260 | return; | 1231 | return; |
1261 | } | ||
1262 | } | 1232 | } |
1263 | 1233 | ||
1264 | /* | 1234 | // Requested engine not defined, warn on console. |
1265 | * Requested engine not defined, warn on console. | 1235 | // Then we try to handle it if we're the default engine, else we ignore it. |
1266 | * Then we try to handle it if we're the default engine, else we ignore it. | ||
1267 | */ | ||
1268 | m_log.Warn ("[XMREngine]: " + itemID.ToString() + " requests undefined/disabled engine " + engineName); | 1236 | m_log.Warn ("[XMREngine]: " + itemID.ToString() + " requests undefined/disabled engine " + engineName); |
1269 | m_log.Info ("[XMREngine]: - " + part.GetWorldPosition ()); | 1237 | m_log.Info ("[XMREngine]: - " + part.GetWorldPosition ()); |
1270 | m_log.Info ("[XMREngine]: first line: " + firstline); | 1238 | m_log.Info ("[XMREngine]: first line: " + firstline); |
1271 | if (defEngine != ScriptEngineName) { | 1239 | if (defEngine != ScriptEngineName) |
1240 | { | ||
1272 | m_log.Info ("[XMREngine]: leaving it to the default script engine (" + defEngine + ") to process it"); | 1241 | m_log.Info ("[XMREngine]: leaving it to the default script engine (" + defEngine + ") to process it"); |
1273 | return; | 1242 | return; |
1274 | } | 1243 | } |
1275 | m_log.Info ("[XMREngine]: will attempt to processing it anyway as default script engine"); | 1244 | m_log.Info ("[XMREngine]: will attempt to processing it anyway as default script engine"); |
1276 | } | 1245 | } |
1277 | 1246 | ||
1278 | /* | 1247 | // Put on object/instance lists. |
1279 | * Put on object/instance lists. | ||
1280 | */ | ||
1281 | XMRInstance instance = (XMRInstance)Activator.CreateInstance (ScriptCodeGen.xmrInstSuperType); | 1248 | XMRInstance instance = (XMRInstance)Activator.CreateInstance (ScriptCodeGen.xmrInstSuperType); |
1282 | instance.m_LocalID = localID; | 1249 | instance.m_LocalID = localID; |
1283 | instance.m_ItemID = itemID; | 1250 | instance.m_ItemID = itemID; |
@@ -1291,7 +1258,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1291 | instance.m_DescName = part.Name + ":" + item.Name; | 1258 | instance.m_DescName = part.Name + ":" + item.Name; |
1292 | instance.m_IState = XMRInstState.CONSTRUCT; | 1259 | instance.m_IState = XMRInstState.CONSTRUCT; |
1293 | 1260 | ||
1294 | lock (m_InstancesDict) { | 1261 | lock (m_InstancesDict) |
1262 | { | ||
1295 | m_LockedDict = "RegisterInstance"; | 1263 | m_LockedDict = "RegisterInstance"; |
1296 | 1264 | ||
1297 | // Insert on internal list of all scripts being handled by this engine instance. | 1265 | // Insert on internal list of all scripts being handled by this engine instance. |
@@ -1300,11 +1268,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1300 | // Insert on internal list of all scripts being handled by this engine instance | 1268 | // Insert on internal list of all scripts being handled by this engine instance |
1301 | // that are part of the object. | 1269 | // that are part of the object. |
1302 | List<UUID> itemIDList; | 1270 | List<UUID> itemIDList; |
1303 | if (!m_ObjectItemList.TryGetValue(instance.m_PartUUID, out itemIDList)) { | 1271 | if (!m_ObjectItemList.TryGetValue(instance.m_PartUUID, out itemIDList)) |
1272 | { | ||
1304 | itemIDList = new List<UUID>(); | 1273 | itemIDList = new List<UUID>(); |
1305 | m_ObjectItemList[instance.m_PartUUID] = itemIDList; | 1274 | m_ObjectItemList[instance.m_PartUUID] = itemIDList; |
1306 | } | 1275 | } |
1307 | if (!itemIDList.Contains(instance.m_ItemID)) { | 1276 | if (!itemIDList.Contains(instance.m_ItemID)) |
1277 | { | ||
1308 | itemIDList.Add(instance.m_ItemID); | 1278 | itemIDList.Add(instance.m_ItemID); |
1309 | m_ObjectInstArray[instance.m_PartUUID] = null; | 1279 | m_ObjectInstArray[instance.m_PartUUID] = null; |
1310 | } | 1280 | } |
@@ -1312,12 +1282,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1312 | m_LockedDict = "~RegisterInstance"; | 1282 | m_LockedDict = "~RegisterInstance"; |
1313 | } | 1283 | } |
1314 | 1284 | ||
1315 | /* | 1285 | // Compile and load it. |
1316 | * Compile and load it. | 1286 | lock (m_ScriptErrors) |
1317 | */ | ||
1318 | lock (m_ScriptErrors) { | ||
1319 | m_ScriptErrors.Remove (instance.m_ItemID); | 1287 | m_ScriptErrors.Remove (instance.m_ItemID); |
1320 | } | 1288 | |
1321 | LoadThreadWork (instance); | 1289 | LoadThreadWork (instance); |
1322 | } | 1290 | } |
1323 | 1291 | ||
@@ -1326,17 +1294,20 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1326 | */ | 1294 | */ |
1327 | private void LoadThreadWork (XMRInstance instance) | 1295 | private void LoadThreadWork (XMRInstance instance) |
1328 | { | 1296 | { |
1329 | /* | 1297 | // Compile and load the script in memory. |
1330 | * Compile and load the script in memory. | 1298 | |
1331 | */ | ||
1332 | ArrayList errors = new ArrayList(); | 1299 | ArrayList errors = new ArrayList(); |
1333 | Exception initerr = null; | 1300 | Exception initerr = null; |
1334 | try { | 1301 | try |
1302 | { | ||
1335 | instance.Initialize(this, m_ScriptBasePath, m_StackSize, m_HeapSize, errors); | 1303 | instance.Initialize(this, m_ScriptBasePath, m_StackSize, m_HeapSize, errors); |
1336 | } catch (Exception e1) { | 1304 | } |
1305 | catch (Exception e1) | ||
1306 | { | ||
1337 | initerr = e1; | 1307 | initerr = e1; |
1338 | } | 1308 | } |
1339 | if ((initerr != null) && !instance.m_ForceRecomp) { | 1309 | if ((initerr != null) && !instance.m_ForceRecomp) |
1310 | { | ||
1340 | UUID itemID = instance.m_ItemID; | 1311 | UUID itemID = instance.m_ItemID; |
1341 | Verbose ("[XMREngine]: {0}/{2} first load failed ({1}), retrying after recompile", | 1312 | Verbose ("[XMREngine]: {0}/{2} first load failed ({1}), retrying after recompile", |
1342 | itemID.ToString(), initerr.Message, instance.m_Item.AssetID.ToString()); | 1313 | itemID.ToString(), initerr.Message, instance.m_Item.AssetID.ToString()); |
@@ -1344,62 +1315,66 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1344 | initerr = null; | 1315 | initerr = null; |
1345 | errors = new ArrayList(); | 1316 | errors = new ArrayList(); |
1346 | instance.m_ForceRecomp = true; | 1317 | instance.m_ForceRecomp = true; |
1347 | try { | 1318 | try |
1319 | { | ||
1348 | instance.Initialize(this, m_ScriptBasePath, m_StackSize, m_HeapSize, errors); | 1320 | instance.Initialize(this, m_ScriptBasePath, m_StackSize, m_HeapSize, errors); |
1349 | } catch (Exception e2) { | 1321 | } |
1322 | catch (Exception e2) | ||
1323 | { | ||
1350 | initerr = e2; | 1324 | initerr = e2; |
1351 | } | 1325 | } |
1352 | } | 1326 | } |
1353 | if (initerr != null) { | 1327 | if (initerr != null) |
1328 | { | ||
1354 | UUID itemID = instance.m_ItemID; | 1329 | UUID itemID = instance.m_ItemID; |
1355 | Verbose ("[XMREngine]: Error starting script {0}/{2}: {1}", | 1330 | Verbose ("[XMREngine]: Error starting script {0}/{2}: {1}", |
1356 | itemID.ToString(), initerr.Message, instance.m_Item.AssetID.ToString()); | 1331 | itemID.ToString(), initerr.Message, instance.m_Item.AssetID.ToString()); |
1357 | if (initerr.Message != "compilation errors") { | 1332 | if (initerr.Message != "compilation errors") |
1333 | { | ||
1358 | Verbose ("[XMREngine]: - " + instance.m_Part.GetWorldPosition () + " " + instance.m_DescName); | 1334 | Verbose ("[XMREngine]: - " + instance.m_Part.GetWorldPosition () + " " + instance.m_DescName); |
1359 | Verbose ("[XMREngine]: exception:\n{0}", initerr.ToString()); | 1335 | Verbose ("[XMREngine]: exception:\n{0}", initerr.ToString()); |
1360 | } | 1336 | } |
1361 | 1337 | ||
1362 | OnRemoveScript (0, itemID); | 1338 | OnRemoveScript (0, itemID); |
1363 | 1339 | ||
1364 | /* | 1340 | // Post errors where GetScriptErrors() can see them. |
1365 | * Post errors where GetScriptErrors() can see them. | 1341 | |
1366 | */ | 1342 | if (errors.Count == 0) |
1367 | if (errors.Count == 0) { | ||
1368 | errors.Add(initerr.Message); | 1343 | errors.Add(initerr.Message); |
1369 | } else { | 1344 | else |
1370 | foreach (Object err in errors) { | 1345 | { |
1346 | foreach (Object err in errors) | ||
1347 | { | ||
1371 | if (m_ScriptDebug) | 1348 | if (m_ScriptDebug) |
1372 | m_log.DebugFormat ("[XMREngine]: {0}", err.ToString()); | 1349 | m_log.DebugFormat ("[XMREngine]: {0}", err.ToString()); |
1373 | } | 1350 | } |
1374 | } | 1351 | } |
1375 | lock (m_ScriptErrors) { | 1352 | |
1353 | lock (m_ScriptErrors) | ||
1376 | m_ScriptErrors[instance.m_ItemID] = errors; | 1354 | m_ScriptErrors[instance.m_ItemID] = errors; |
1377 | } | ||
1378 | 1355 | ||
1379 | return; | 1356 | return; |
1380 | } | 1357 | } |
1381 | 1358 | ||
1382 | /* | 1359 | // Tell GetScriptErrors() that we have finished compiling/loading |
1383 | * Tell GetScriptErrors() that we have finished compiling/loading | 1360 | // successfully (by posting a 0 element array). |
1384 | * successfully (by posting a 0 element array). | 1361 | lock (m_ScriptErrors) |
1385 | */ | 1362 | { |
1386 | lock (m_ScriptErrors) { | ||
1387 | if (instance.m_IState != XMRInstState.CONSTRUCT) throw new Exception("bad state"); | 1363 | if (instance.m_IState != XMRInstState.CONSTRUCT) throw new Exception("bad state"); |
1388 | m_ScriptErrors[instance.m_ItemID] = noScriptErrors; | 1364 | m_ScriptErrors[instance.m_ItemID] = noScriptErrors; |
1389 | } | 1365 | } |
1390 | 1366 | ||
1391 | /* | 1367 | // Transition from CONSTRUCT->ONSTARTQ and give to RunScriptThread(). |
1392 | * Transition from CONSTRUCT->ONSTARTQ and give to RunScriptThread(). | 1368 | // Put it on the start queue so it will run any queued event handlers, |
1393 | * Put it on the start queue so it will run any queued event handlers, | 1369 | // such as state_entry() or on_rez(). If there aren't any queued, it |
1394 | * such as state_entry() or on_rez(). If there aren't any queued, it | 1370 | // will just go to idle state when RunOne() tries to dequeue an event. |
1395 | * will just go to idle state when RunOne() tries to dequeue an event. | 1371 | lock (instance.m_QueueLock) |
1396 | */ | 1372 | { |
1397 | lock (instance.m_QueueLock) { | 1373 | if (instance.m_IState != XMRInstState.CONSTRUCT) |
1398 | if (instance.m_IState != XMRInstState.CONSTRUCT) throw new Exception("bad state"); | 1374 | throw new Exception("bad state"); |
1399 | instance.m_IState = XMRInstState.ONSTARTQ; | 1375 | instance.m_IState = XMRInstState.ONSTARTQ; |
1400 | if (!instance.m_Running) { | 1376 | if (!instance.m_Running) |
1401 | instance.EmptyEventQueues (); | 1377 | instance.EmptyEventQueues (); |
1402 | } | ||
1403 | } | 1378 | } |
1404 | QueueToStart(instance); | 1379 | QueueToStart(instance); |
1405 | } | 1380 | } |
@@ -1408,66 +1383,57 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1408 | { | 1383 | { |
1409 | TraceCalls("[XMREngine]: OnRemoveScript(...,{0})", itemID.ToString()); | 1384 | TraceCalls("[XMREngine]: OnRemoveScript(...,{0})", itemID.ToString()); |
1410 | 1385 | ||
1411 | /* | 1386 | // Remove from our list of known scripts. |
1412 | * Remove from our list of known scripts. | 1387 | // After this, no more events can queue because we won't be |
1413 | * After this, no more events can queue because we won't be | 1388 | // able to translate the itemID to an XMRInstance pointer. |
1414 | * able to translate the itemID to an XMRInstance pointer. | 1389 | |
1415 | */ | ||
1416 | XMRInstance instance = null; | 1390 | XMRInstance instance = null; |
1417 | lock (m_InstancesDict) | 1391 | lock (m_InstancesDict) |
1418 | { | 1392 | { |
1419 | m_LockedDict = "OnRemoveScript:" + itemID.ToString(); | 1393 | m_LockedDict = "OnRemoveScript:" + itemID.ToString(); |
1420 | 1394 | ||
1421 | /* | 1395 | // Tell the instance to free off everything it can. |
1422 | * Tell the instance to free off everything it can. | 1396 | |
1423 | */ | ||
1424 | if (!m_InstancesDict.TryGetValue(itemID, out instance)) | 1397 | if (!m_InstancesDict.TryGetValue(itemID, out instance)) |
1425 | { | 1398 | { |
1426 | m_LockedDict = "~OnRemoveScript"; | 1399 | m_LockedDict = "~OnRemoveScript"; |
1427 | return; | 1400 | return; |
1428 | } | 1401 | } |
1429 | 1402 | ||
1430 | /* | 1403 | // Tell it to stop executing anything. |
1431 | * Tell it to stop executing anything. | ||
1432 | */ | ||
1433 | instance.suspendOnCheckRunHold = true; | 1404 | instance.suspendOnCheckRunHold = true; |
1434 | 1405 | ||
1435 | /* | 1406 | // Remove it from our list of known script instances |
1436 | * Remove it from our list of known script instances | 1407 | // mostly so no more events can queue to it. |
1437 | * mostly so no more events can queue to it. | ||
1438 | */ | ||
1439 | m_InstancesDict.Remove(itemID); | 1408 | m_InstancesDict.Remove(itemID); |
1440 | 1409 | ||
1441 | List<UUID> itemIDList; | 1410 | List<UUID> itemIDList; |
1442 | if (m_ObjectItemList.TryGetValue (instance.m_PartUUID, out itemIDList)) { | 1411 | if (m_ObjectItemList.TryGetValue (instance.m_PartUUID, out itemIDList)) |
1412 | { | ||
1443 | itemIDList.Remove(itemID); | 1413 | itemIDList.Remove(itemID); |
1444 | if (itemIDList.Count == 0) { | 1414 | if (itemIDList.Count == 0) |
1415 | { | ||
1445 | m_ObjectItemList.Remove(instance.m_PartUUID); | 1416 | m_ObjectItemList.Remove(instance.m_PartUUID); |
1446 | m_ObjectInstArray.Remove(instance.m_PartUUID); | 1417 | m_ObjectInstArray.Remove(instance.m_PartUUID); |
1447 | } else { | ||
1448 | m_ObjectInstArray[instance.m_PartUUID] = null; | ||
1449 | } | 1418 | } |
1419 | else | ||
1420 | m_ObjectInstArray[instance.m_PartUUID] = null; | ||
1450 | } | 1421 | } |
1451 | 1422 | ||
1452 | /* | 1423 | // Delete the .state file as any needed contents were fetched with GetXMLState() |
1453 | * Delete the .state file as any needed contents were fetched with GetXMLState() | 1424 | // and stored on the database server. |
1454 | * and stored on the database server. | ||
1455 | */ | ||
1456 | string stateFileName = XMRInstance.GetStateFileName(m_ScriptBasePath, itemID); | 1425 | string stateFileName = XMRInstance.GetStateFileName(m_ScriptBasePath, itemID); |
1457 | File.Delete(stateFileName); | 1426 | File.Delete(stateFileName); |
1458 | 1427 | ||
1459 | ScriptRemoved handlerScriptRemoved = OnScriptRemoved; | 1428 | ScriptRemoved handlerScriptRemoved = OnScriptRemoved; |
1460 | if (handlerScriptRemoved != null) { | 1429 | if (handlerScriptRemoved != null) |
1461 | handlerScriptRemoved(itemID); | 1430 | handlerScriptRemoved(itemID); |
1462 | } | ||
1463 | 1431 | ||
1464 | m_LockedDict = "~~OnRemoveScript"; | 1432 | m_LockedDict = "~~OnRemoveScript"; |
1465 | } | 1433 | } |
1466 | 1434 | ||
1467 | /* | 1435 | // Free off its stack and fun things like that. |
1468 | * Free off its stack and fun things like that. | 1436 | // If it is running, abort it. |
1469 | * If it is running, abort it. | ||
1470 | */ | ||
1471 | instance.Dispose (); | 1437 | instance.Dispose (); |
1472 | } | 1438 | } |
1473 | 1439 | ||
@@ -1480,31 +1446,33 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1480 | public void OnStartScript(uint localID, UUID itemID) | 1446 | public void OnStartScript(uint localID, UUID itemID) |
1481 | { | 1447 | { |
1482 | XMRInstance instance = GetInstance (itemID); | 1448 | XMRInstance instance = GetInstance (itemID); |
1483 | if (instance != null) { | 1449 | if (instance != null) |
1484 | instance.Running = true; | 1450 | instance.Running = true; |
1485 | } | ||
1486 | } | 1451 | } |
1487 | 1452 | ||
1488 | public void OnStopScript(uint localID, UUID itemID) | 1453 | public void OnStopScript(uint localID, UUID itemID) |
1489 | { | 1454 | { |
1490 | XMRInstance instance = GetInstance (itemID); | 1455 | XMRInstance instance = GetInstance (itemID); |
1491 | if (instance != null) { | 1456 | if (instance != null) |
1492 | instance.Running = false; | 1457 | instance.Running = false; |
1493 | } | ||
1494 | } | 1458 | } |
1495 | 1459 | ||
1496 | public void OnGetScriptRunning(IClientAPI controllingClient, | 1460 | public void OnGetScriptRunning(IClientAPI controllingClient, |
1497 | UUID objectID, UUID itemID) | 1461 | UUID objectID, UUID itemID) |
1498 | { | 1462 | { |
1499 | XMRInstance instance = GetInstance (itemID); | 1463 | XMRInstance instance = GetInstance (itemID); |
1500 | if (instance != null) { | 1464 | if (instance != null) |
1465 | { | ||
1501 | TraceCalls("[XMREngine]: XMREngine.OnGetScriptRunning({0},{1})", objectID.ToString(), itemID.ToString()); | 1466 | TraceCalls("[XMREngine]: XMREngine.OnGetScriptRunning({0},{1})", objectID.ToString(), itemID.ToString()); |
1502 | 1467 | ||
1503 | IEventQueue eq = World.RequestModuleInterface<IEventQueue>(); | 1468 | IEventQueue eq = World.RequestModuleInterface<IEventQueue>(); |
1504 | if (eq == null) { | 1469 | if (eq == null) |
1470 | { | ||
1505 | controllingClient.SendScriptRunningReply(objectID, itemID, | 1471 | controllingClient.SendScriptRunningReply(objectID, itemID, |
1506 | instance.Running); | 1472 | instance.Running); |
1507 | } else { | 1473 | } |
1474 | else | ||
1475 | { | ||
1508 | eq.Enqueue(EventQueueHelper.ScriptRunningReplyEvent(objectID, | 1476 | eq.Enqueue(EventQueueHelper.ScriptRunningReplyEvent(objectID, |
1509 | itemID, instance.Running, true), | 1477 | itemID, instance.Running, true), |
1510 | controllingClient.AgentId); | 1478 | controllingClient.AgentId); |
@@ -1515,7 +1483,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1515 | public bool HasScript(UUID itemID, out bool running) | 1483 | public bool HasScript(UUID itemID, out bool running) |
1516 | { | 1484 | { |
1517 | XMRInstance instance = GetInstance (itemID); | 1485 | XMRInstance instance = GetInstance (itemID); |
1518 | if (instance == null) { | 1486 | if (instance == null) |
1487 | { | ||
1519 | running = true; | 1488 | running = true; |
1520 | return false; | 1489 | return false; |
1521 | } | 1490 | } |
@@ -1529,9 +1498,11 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1529 | */ | 1498 | */ |
1530 | private void OnFrame () | 1499 | private void OnFrame () |
1531 | { | 1500 | { |
1532 | if (m_FrameUpdateList != null) { | 1501 | if (m_FrameUpdateList != null) |
1502 | { | ||
1533 | ThreadStart frameupdates; | 1503 | ThreadStart frameupdates; |
1534 | lock (m_FrameUpdateLock) { | 1504 | lock (m_FrameUpdateLock) |
1505 | { | ||
1535 | frameupdates = m_FrameUpdateList; | 1506 | frameupdates = m_FrameUpdateList; |
1536 | m_FrameUpdateList = null; | 1507 | m_FrameUpdateList = null; |
1537 | } | 1508 | } |
@@ -1545,9 +1516,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1545 | */ | 1516 | */ |
1546 | public void AddOnFrameUpdate (ThreadStart thunk) | 1517 | public void AddOnFrameUpdate (ThreadStart thunk) |
1547 | { | 1518 | { |
1548 | lock (m_FrameUpdateLock) { | 1519 | lock (m_FrameUpdateLock) |
1549 | m_FrameUpdateList += thunk; | 1520 | m_FrameUpdateList += thunk; |
1550 | } | ||
1551 | } | 1521 | } |
1552 | 1522 | ||
1553 | /** | 1523 | /** |
@@ -1570,7 +1540,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1570 | */ | 1540 | */ |
1571 | public void QueueToStart(XMRInstance inst) | 1541 | public void QueueToStart(XMRInstance inst) |
1572 | { | 1542 | { |
1573 | lock (m_StartQueue) { | 1543 | lock (m_StartQueue) |
1544 | { | ||
1574 | if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); | 1545 | if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); |
1575 | m_StartQueue.InsertTail(inst); | 1546 | m_StartQueue.InsertTail(inst); |
1576 | } | 1547 | } |
@@ -1582,28 +1553,25 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1582 | */ | 1553 | */ |
1583 | public void WakeFromSleep(XMRInstance inst) | 1554 | public void WakeFromSleep(XMRInstance inst) |
1584 | { | 1555 | { |
1585 | /* | 1556 | // Remove from sleep queue unless someone else already woke it. |
1586 | * Remove from sleep queue unless someone else already woke it. | 1557 | lock (m_SleepQueue) |
1587 | */ | 1558 | { |
1588 | lock (m_SleepQueue) { | 1559 | if (inst.m_IState != XMRInstState.ONSLEEPQ) |
1589 | if (inst.m_IState != XMRInstState.ONSLEEPQ) { | ||
1590 | return; | 1560 | return; |
1591 | } | 1561 | |
1592 | m_SleepQueue.Remove(inst); | 1562 | m_SleepQueue.Remove(inst); |
1593 | inst.m_IState = XMRInstState.REMDFROMSLPQ; | 1563 | inst.m_IState = XMRInstState.REMDFROMSLPQ; |
1594 | } | 1564 | } |
1595 | 1565 | ||
1596 | /* | 1566 | // Put on end of list of scripts that are ready to run. |
1597 | * Put on end of list of scripts that are ready to run. | 1567 | lock (m_YieldQueue) |
1598 | */ | 1568 | { |
1599 | lock (m_YieldQueue) { | ||
1600 | inst.m_IState = XMRInstState.ONYIELDQ; | 1569 | inst.m_IState = XMRInstState.ONYIELDQ; |
1601 | m_YieldQueue.InsertTail(inst); | 1570 | m_YieldQueue.InsertTail(inst); |
1602 | } | 1571 | } |
1603 | 1572 | ||
1604 | /* | 1573 | |
1605 | * Make sure the OS thread is running so it will see the script. | 1574 | // Make sure the OS thread is running so it will see the script. |
1606 | */ | ||
1607 | XMRScriptThread.WakeUpOne(); | 1575 | XMRScriptThread.WakeUpOne(); |
1608 | } | 1576 | } |
1609 | 1577 | ||
@@ -1616,96 +1584,89 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1616 | */ | 1584 | */ |
1617 | public void HandleNewIState(XMRInstance inst, XMRInstState newIState) | 1585 | public void HandleNewIState(XMRInstance inst, XMRInstState newIState) |
1618 | { | 1586 | { |
1619 | /* | ||
1620 | * RunOne() should have left the instance in RUNNING state. | ||
1621 | */ | ||
1622 | if (inst.m_IState != XMRInstState.RUNNING) throw new Exception("bad state"); | ||
1623 | 1587 | ||
1624 | /* | 1588 | // RunOne() should have left the instance in RUNNING state. |
1625 | * Now see what RunOne() wants us to do with the instance next. | 1589 | if (inst.m_IState != XMRInstState.RUNNING) |
1626 | */ | 1590 | throw new Exception("bad state"); |
1627 | switch (newIState) { | 1591 | |
1628 | 1592 | ||
1629 | /* | 1593 | // Now see what RunOne() wants us to do with the instance next. |
1630 | * Instance has set m_SleepUntil to when it wants to sleep until. | 1594 | switch (newIState) |
1631 | * So insert instance in sleep queue by ascending wake time. | 1595 | { |
1632 | * Then wake the timer thread if this is the new first entry | 1596 | |
1633 | * so it will reset its timer. | 1597 | // Instance has set m_SleepUntil to when it wants to sleep until. |
1634 | */ | 1598 | // So insert instance in sleep queue by ascending wake time. |
1635 | case XMRInstState.ONSLEEPQ: { | 1599 | // Then wake the timer thread if this is the new first entry |
1636 | lock (m_SleepQueue) { | 1600 | // so it will reset its timer. |
1601 | case XMRInstState.ONSLEEPQ: | ||
1602 | lock (m_SleepQueue) | ||
1603 | { | ||
1637 | XMRInstance after; | 1604 | XMRInstance after; |
1638 | 1605 | ||
1639 | inst.m_IState = XMRInstState.ONSLEEPQ; | 1606 | inst.m_IState = XMRInstState.ONSLEEPQ; |
1640 | for (after = m_SleepQueue.PeekHead(); after != null; after = after.m_NextInst) { | 1607 | for (after = m_SleepQueue.PeekHead(); after != null; after = after.m_NextInst) |
1641 | if (after.m_SleepUntil > inst.m_SleepUntil) break; | 1608 | { |
1609 | if (after.m_SleepUntil > inst.m_SleepUntil) | ||
1610 | break; | ||
1642 | } | 1611 | } |
1643 | m_SleepQueue.InsertBefore(inst, after); | 1612 | m_SleepQueue.InsertBefore(inst, after); |
1644 | if (m_SleepQueue.PeekHead() == inst) { | 1613 | if (m_SleepQueue.PeekHead() == inst) |
1614 | { | ||
1645 | Monitor.Pulse (m_SleepQueue); | 1615 | Monitor.Pulse (m_SleepQueue); |
1646 | } | 1616 | } |
1647 | } | 1617 | } |
1648 | break; | 1618 | break; |
1649 | } | ||
1650 | 1619 | ||
1651 | /* | 1620 | // Instance just took a long time to run and got wacked by the |
1652 | * Instance just took a long time to run and got wacked by the | 1621 | // slicer. So put on end of yield queue to let someone else |
1653 | * slicer. So put on end of yield queue to let someone else | 1622 | // run. If there is no one else, it will run again right away. |
1654 | * run. If there is no one else, it will run again right away. | 1623 | case XMRInstState.ONYIELDQ: |
1655 | */ | 1624 | lock (m_YieldQueue) |
1656 | case XMRInstState.ONYIELDQ: { | 1625 | { |
1657 | lock (m_YieldQueue) { | ||
1658 | inst.m_IState = XMRInstState.ONYIELDQ; | 1626 | inst.m_IState = XMRInstState.ONYIELDQ; |
1659 | m_YieldQueue.InsertTail(inst); | 1627 | m_YieldQueue.InsertTail(inst); |
1660 | } | 1628 | } |
1661 | break; | 1629 | break; |
1662 | } | ||
1663 | 1630 | ||
1664 | /* | 1631 | // Instance finished executing an event handler. So if there is |
1665 | * Instance finished executing an event handler. So if there is | 1632 | // another event queued for it, put it on the start queue so it |
1666 | * another event queued for it, put it on the start queue so it | 1633 | // will process the new event. Otherwise, mark it idle and the |
1667 | * will process the new event. Otherwise, mark it idle and the | 1634 | // next event to queue to it will start it up. |
1668 | * next event to queue to it will start it up. | 1635 | case XMRInstState.FINISHED: |
1669 | */ | ||
1670 | case XMRInstState.FINISHED: { | ||
1671 | Monitor.Enter(inst.m_QueueLock); | 1636 | Monitor.Enter(inst.m_QueueLock); |
1672 | if (!inst.m_Suspended && (inst.m_EventQueue.Count > 0)) { | 1637 | if (!inst.m_Suspended && (inst.m_EventQueue.Count > 0)) |
1638 | { | ||
1673 | Monitor.Exit(inst.m_QueueLock); | 1639 | Monitor.Exit(inst.m_QueueLock); |
1674 | lock (m_StartQueue) { | 1640 | lock (m_StartQueue) |
1641 | { | ||
1675 | inst.m_IState = XMRInstState.ONSTARTQ; | 1642 | inst.m_IState = XMRInstState.ONSTARTQ; |
1676 | m_StartQueue.InsertTail (inst); | 1643 | m_StartQueue.InsertTail (inst); |
1677 | } | 1644 | } |
1678 | } else { | 1645 | } |
1646 | else | ||
1647 | { | ||
1679 | inst.m_IState = XMRInstState.IDLE; | 1648 | inst.m_IState = XMRInstState.IDLE; |
1680 | Monitor.Exit(inst.m_QueueLock); | 1649 | Monitor.Exit(inst.m_QueueLock); |
1681 | } | 1650 | } |
1682 | break; | 1651 | break; |
1683 | } | ||
1684 | 1652 | ||
1685 | /* | 1653 | // Its m_SuspendCount > 0. |
1686 | * Its m_SuspendCount > 0. | 1654 | // Don't put it on any queue and it won't run. |
1687 | * Don't put it on any queue and it won't run. | 1655 | // Since it's not IDLE, even queuing an event won't start it. |
1688 | * Since it's not IDLE, even queuing an event won't start it. | 1656 | case XMRInstState.SUSPENDED: |
1689 | */ | ||
1690 | case XMRInstState.SUSPENDED: { | ||
1691 | inst.m_IState = XMRInstState.SUSPENDED; | 1657 | inst.m_IState = XMRInstState.SUSPENDED; |
1692 | break; | 1658 | break; |
1693 | } | ||
1694 | 1659 | ||
1695 | /* | 1660 | // It has been disposed of. |
1696 | * It has been disposed of. | 1661 | // Just set the new state and all refs should theoretically drop off |
1697 | * Just set the new state and all refs should theoretically drop off | 1662 | // as the instance is no longer in any list. |
1698 | * as the instance is no longer in any list. | 1663 | case XMRInstState.DISPOSED: |
1699 | */ | ||
1700 | case XMRInstState.DISPOSED: { | ||
1701 | inst.m_IState = XMRInstState.DISPOSED; | 1664 | inst.m_IState = XMRInstState.DISPOSED; |
1702 | break; | 1665 | break; |
1703 | } | ||
1704 | 1666 | ||
1705 | /* | 1667 | // RunOne returned something bad. |
1706 | * RunOne returned something bad. | 1668 | default: |
1707 | */ | 1669 | throw new Exception("bad new state"); |
1708 | default: throw new Exception("bad new state"); | ||
1709 | } | 1670 | } |
1710 | } | 1671 | } |
1711 | 1672 | ||
@@ -1718,45 +1679,48 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1718 | int deltaMS; | 1679 | int deltaMS; |
1719 | XMRInstance inst; | 1680 | XMRInstance inst; |
1720 | 1681 | ||
1721 | while (true) { | 1682 | while (true) |
1722 | lock (m_SleepQueue) { | 1683 | { |
1684 | lock (m_SleepQueue) | ||
1685 | { | ||
1723 | 1686 | ||
1724 | /* | 1687 | // Wait here until there is a script on the timer queue that has expired. |
1725 | * Wait here until there is a script on the timer queue that has expired. | 1688 | while (true) |
1726 | */ | 1689 | { |
1727 | while (true) { | ||
1728 | UpdateMyThread (); | 1690 | UpdateMyThread (); |
1729 | if (m_Exiting) { | 1691 | if (m_Exiting) |
1692 | { | ||
1730 | MyThreadExiting (); | 1693 | MyThreadExiting (); |
1731 | return; | 1694 | return; |
1732 | } | 1695 | } |
1733 | inst = m_SleepQueue.PeekHead(); | 1696 | inst = m_SleepQueue.PeekHead(); |
1734 | if (inst == null) { | 1697 | if (inst == null) |
1698 | { | ||
1735 | Monitor.Wait (m_SleepQueue, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); | 1699 | Monitor.Wait (m_SleepQueue, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); |
1736 | continue; | 1700 | continue; |
1737 | } | 1701 | } |
1738 | if (inst.m_IState != XMRInstState.ONSLEEPQ) throw new Exception("bad state"); | 1702 | if (inst.m_IState != XMRInstState.ONSLEEPQ) throw new Exception("bad state"); |
1739 | deltaTS = (inst.m_SleepUntil - DateTime.UtcNow).TotalMilliseconds; | 1703 | deltaTS = (inst.m_SleepUntil - DateTime.UtcNow).TotalMilliseconds; |
1740 | if (deltaTS <= 0.0) break; | 1704 | if (deltaTS <= 0.0) |
1705 | break; | ||
1741 | deltaMS = Int32.MaxValue; | 1706 | deltaMS = Int32.MaxValue; |
1742 | if (deltaTS < Int32.MaxValue) deltaMS = (int)deltaTS; | 1707 | if (deltaTS < Int32.MaxValue) |
1743 | if (deltaMS > Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2) { | 1708 | deltaMS = (int)deltaTS; |
1709 | if (deltaMS > Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2) | ||
1710 | { | ||
1744 | deltaMS = Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2; | 1711 | deltaMS = Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2; |
1745 | } | 1712 | } |
1746 | Monitor.Wait (m_SleepQueue, deltaMS); | 1713 | Monitor.Wait (m_SleepQueue, deltaMS); |
1747 | } | 1714 | } |
1748 | 1715 | ||
1749 | /* | 1716 | // Remove the expired entry from the timer queue. |
1750 | * Remove the expired entry from the timer queue. | ||
1751 | */ | ||
1752 | m_SleepQueue.RemoveHead(); | 1717 | m_SleepQueue.RemoveHead(); |
1753 | inst.m_IState = XMRInstState.REMDFROMSLPQ; | 1718 | inst.m_IState = XMRInstState.REMDFROMSLPQ; |
1754 | } | 1719 | } |
1755 | 1720 | ||
1756 | /* | 1721 | // Post the script to the yield queue so it will run and wake a script thread to run it. |
1757 | * Post the script to the yield queue so it will run and wake a script thread to run it. | 1722 | lock (m_YieldQueue) |
1758 | */ | 1723 | { |
1759 | lock (m_YieldQueue) { | ||
1760 | inst.m_IState = XMRInstState.ONYIELDQ; | 1724 | inst.m_IState = XMRInstState.ONYIELDQ; |
1761 | m_YieldQueue.InsertTail(inst); | 1725 | m_YieldQueue.InsertTail(inst); |
1762 | } | 1726 | } |
@@ -1767,42 +1731,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1767 | /** | 1731 | /** |
1768 | * @brief Thread that runs a time slicer. | 1732 | * @brief Thread that runs a time slicer. |
1769 | */ | 1733 | */ |
1770 | /* | ||
1771 | private void RunSliceThread() | ||
1772 | { | ||
1773 | int ms = m_Config.GetInt ("TimeSlice", 50); | ||
1774 | while (!m_Exiting) { | ||
1775 | UpdateMyThread (); | ||
1776 | */ | ||
1777 | /* | ||
1778 | * Let script run for a little bit. | ||
1779 | */ | ||
1780 | // System.Threading.Thread.Sleep (ms); | ||
1781 | |||
1782 | /* | ||
1783 | * If some script is running, flag it to suspend | ||
1784 | * next time it calls CheckRun(). | ||
1785 | */ | ||
1786 | /* for (int i = 0; i < numThreadScriptWorkers; i ++) { | ||
1787 | XMRScriptThread st = m_ScriptThreads[i]; | ||
1788 | if (st != null) st.TimeSlice(); | ||
1789 | } | ||
1790 | } | ||
1791 | MyThreadExiting (); | ||
1792 | } | ||
1793 | */ | ||
1794 | public void Suspend(UUID itemID, int ms) | 1734 | public void Suspend(UUID itemID, int ms) |
1795 | { | 1735 | { |
1796 | XMRInstance instance = GetInstance (itemID); | 1736 | XMRInstance instance = GetInstance (itemID); |
1797 | if (instance != null) { | 1737 | if (instance != null) |
1798 | instance.Sleep(ms); | 1738 | instance.Sleep(ms); |
1799 | } | ||
1800 | } | 1739 | } |
1801 | 1740 | ||
1802 | public void Die(UUID itemID) | 1741 | public void Die(UUID itemID) |
1803 | { | 1742 | { |
1804 | XMRInstance instance = GetInstance (itemID); | 1743 | XMRInstance instance = GetInstance (itemID); |
1805 | if (instance != null) { | 1744 | if (instance != null) |
1745 | { | ||
1806 | TraceCalls("[XMREngine]: XMREngine.Die({0})", itemID.ToString()); | 1746 | TraceCalls("[XMREngine]: XMREngine.Die({0})", itemID.ToString()); |
1807 | instance.Die(); | 1747 | instance.Die(); |
1808 | } | 1748 | } |
@@ -1819,10 +1759,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1819 | public XMRInstance GetInstance(UUID itemID) | 1759 | public XMRInstance GetInstance(UUID itemID) |
1820 | { | 1760 | { |
1821 | XMRInstance instance; | 1761 | XMRInstance instance; |
1822 | lock (m_InstancesDict) { | 1762 | lock (m_InstancesDict) |
1823 | if (!m_InstancesDict.TryGetValue(itemID, out instance)) { | 1763 | { |
1764 | if (!m_InstancesDict.TryGetValue(itemID, out instance)) | ||
1824 | instance = null; | 1765 | instance = null; |
1825 | } | ||
1826 | } | 1766 | } |
1827 | return instance; | 1767 | return instance; |
1828 | } | 1768 | } |
@@ -1834,9 +1774,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1834 | { | 1774 | { |
1835 | XMRInstance[] instanceArray; | 1775 | XMRInstance[] instanceArray; |
1836 | 1776 | ||
1837 | lock (m_InstancesDict) { | 1777 | lock (m_InstancesDict) |
1838 | instanceArray = System.Linq.Enumerable.ToArray(m_InstancesDict.Values); | 1778 | instanceArray = System.Linq.Enumerable.ToArray(m_InstancesDict.Values); |
1839 | } | 1779 | |
1840 | foreach (XMRInstance ins in instanceArray) | 1780 | foreach (XMRInstance ins in instanceArray) |
1841 | { | 1781 | { |
1842 | // Don't save attachments | 1782 | // Don't save attachments |
@@ -1856,8 +1796,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1856 | { | 1796 | { |
1857 | ArrayList errors; | 1797 | ArrayList errors; |
1858 | 1798 | ||
1859 | lock (m_ScriptErrors) { | 1799 | lock (m_ScriptErrors) |
1860 | while (!m_ScriptErrors.TryGetValue (itemID, out errors)) { | 1800 | { |
1801 | while (!m_ScriptErrors.TryGetValue (itemID, out errors)) | ||
1802 | { | ||
1861 | Monitor.Wait (m_ScriptErrors); | 1803 | Monitor.Wait (m_ScriptErrors); |
1862 | } | 1804 | } |
1863 | m_ScriptErrors.Remove (itemID); | 1805 | m_ScriptErrors.Remove (itemID); |
@@ -1871,13 +1813,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1871 | public Dictionary<uint, float> GetObjectScriptsExecutionTimes () | 1813 | public Dictionary<uint, float> GetObjectScriptsExecutionTimes () |
1872 | { | 1814 | { |
1873 | Dictionary<uint, float> topScripts = new Dictionary<uint, float> (); | 1815 | Dictionary<uint, float> topScripts = new Dictionary<uint, float> (); |
1874 | lock (m_InstancesDict) { | 1816 | lock (m_InstancesDict) |
1875 | foreach (XMRInstance instance in m_InstancesDict.Values) { | 1817 | { |
1818 | foreach (XMRInstance instance in m_InstancesDict.Values) | ||
1819 | { | ||
1876 | uint rootLocalID = instance.m_Part.ParentGroup.LocalId; | 1820 | uint rootLocalID = instance.m_Part.ParentGroup.LocalId; |
1877 | float oldTotal; | 1821 | float oldTotal; |
1878 | if (!topScripts.TryGetValue (rootLocalID, out oldTotal)) { | 1822 | if (!topScripts.TryGetValue (rootLocalID, out oldTotal)) |
1879 | oldTotal = 0; | 1823 | oldTotal = 0; |
1880 | } | 1824 | |
1881 | topScripts[rootLocalID] = (float)instance.m_CPUTime + oldTotal; | 1825 | topScripts[rootLocalID] = (float)instance.m_CPUTime + oldTotal; |
1882 | } | 1826 | } |
1883 | } | 1827 | } |
@@ -1892,15 +1836,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1892 | */ | 1836 | */ |
1893 | public float GetScriptExecutionTime (List<UUID> itemIDs) | 1837 | public float GetScriptExecutionTime (List<UUID> itemIDs) |
1894 | { | 1838 | { |
1895 | if ((itemIDs == null) || (itemIDs.Count == 0)) { | 1839 | if ((itemIDs == null) || (itemIDs.Count == 0)) |
1896 | return 0; | 1840 | return 0; |
1897 | } | 1841 | |
1898 | float time = 0; | 1842 | float time = 0; |
1899 | foreach (UUID itemID in itemIDs) { | 1843 | foreach (UUID itemID in itemIDs) |
1844 | { | ||
1900 | XMRInstance instance = GetInstance (itemID); | 1845 | XMRInstance instance = GetInstance (itemID); |
1901 | if ((instance != null) && instance.Running) { | 1846 | if ((instance != null) && instance.Running) |
1902 | time += (float) instance.m_CPUTime; | 1847 | time += (float) instance.m_CPUTime; |
1903 | } | ||
1904 | } | 1848 | } |
1905 | return time; | 1849 | return time; |
1906 | } | 1850 | } |
@@ -1911,7 +1855,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1911 | public void SuspendScript(UUID itemID) | 1855 | public void SuspendScript(UUID itemID) |
1912 | { | 1856 | { |
1913 | XMRInstance instance = GetInstance (itemID); | 1857 | XMRInstance instance = GetInstance (itemID); |
1914 | if (instance != null) { | 1858 | if (instance != null) |
1859 | { | ||
1915 | TraceCalls("[XMREngine]: XMREngine.SuspendScript({0})", itemID.ToString()); | 1860 | TraceCalls("[XMREngine]: XMREngine.SuspendScript({0})", itemID.ToString()); |
1916 | instance.SuspendIt(); | 1861 | instance.SuspendIt(); |
1917 | } | 1862 | } |
@@ -1923,10 +1868,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1923 | public void ResumeScript(UUID itemID) | 1868 | public void ResumeScript(UUID itemID) |
1924 | { | 1869 | { |
1925 | XMRInstance instance = GetInstance (itemID); | 1870 | XMRInstance instance = GetInstance (itemID); |
1926 | if (instance != null) { | 1871 | if (instance != null) |
1872 | { | ||
1927 | TraceCalls("[XMREngine]: XMREngine.ResumeScript({0})", itemID.ToString()); | 1873 | TraceCalls("[XMREngine]: XMREngine.ResumeScript({0})", itemID.ToString()); |
1928 | instance.ResumeIt(); | 1874 | instance.ResumeIt(); |
1929 | } else { | 1875 | } |
1876 | else | ||
1877 | { | ||
1930 | // probably an XEngine script | 1878 | // probably an XEngine script |
1931 | } | 1879 | } |
1932 | } | 1880 | } |
@@ -1939,13 +1887,17 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1939 | { | 1887 | { |
1940 | List<UUID> itemIDList = m_ObjectItemList[partUUID]; | 1888 | List<UUID> itemIDList = m_ObjectItemList[partUUID]; |
1941 | int n = 0; | 1889 | int n = 0; |
1942 | foreach (UUID itemID in itemIDList) { | 1890 | foreach (UUID itemID in itemIDList) |
1943 | if (m_InstancesDict.ContainsKey (itemID)) n ++; | 1891 | { |
1892 | if (m_InstancesDict.ContainsKey(itemID)) | ||
1893 | n ++; | ||
1944 | } | 1894 | } |
1945 | XMRInstance[] a = new XMRInstance[n]; | 1895 | XMRInstance[] a = new XMRInstance[n]; |
1946 | n = 0; | 1896 | n = 0; |
1947 | foreach (UUID itemID in itemIDList) { | 1897 | foreach (UUID itemID in itemIDList) |
1948 | if (m_InstancesDict.TryGetValue (itemID, out a[n])) n ++; | 1898 | { |
1899 | if (m_InstancesDict.TryGetValue (itemID, out a[n])) | ||
1900 | n ++; | ||
1949 | } | 1901 | } |
1950 | m_ObjectInstArray[partUUID] = a; | 1902 | m_ObjectInstArray[partUUID] = a; |
1951 | return a; | 1903 | return a; |
@@ -1953,11 +1905,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1953 | 1905 | ||
1954 | public void TraceCalls (string format, params object[] args) | 1906 | public void TraceCalls (string format, params object[] args) |
1955 | { | 1907 | { |
1956 | if (m_TraceCalls) m_log.DebugFormat (format, args); | 1908 | if (m_TraceCalls) |
1909 | m_log.DebugFormat (format, args); | ||
1957 | } | 1910 | } |
1958 | public void Verbose (string format, params object[] args) | 1911 | public void Verbose (string format, params object[] args) |
1959 | { | 1912 | { |
1960 | if (m_Verbose) m_log.DebugFormat (format, args); | 1913 | if (m_Verbose) |
1914 | m_log.DebugFormat (format, args); | ||
1961 | } | 1915 | } |
1962 | 1916 | ||
1963 | /** | 1917 | /** |
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs index fdf65cf..0e7d303 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs | |||
@@ -119,6 +119,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
119 | //FAST: return ++ counter; | 119 | //FAST: return ++ counter; |
120 | 120 | ||
121 | // VS2017 in debug mode seems content to run this quickly though: | 121 | // VS2017 in debug mode seems content to run this quickly though: |
122 | |||
122 | try { | 123 | try { |
123 | return lis.Size; | 124 | return lis.Size; |
124 | } catch { | 125 | } catch { |
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs index fbdf1bf..82759ee 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs | |||
@@ -31,7 +31,6 @@ using System.Collections.Generic; | |||
31 | using System.Globalization; | 31 | using System.Globalization; |
32 | using System.IO; | 32 | using System.IO; |
33 | using System.Reflection.Emit; | 33 | using System.Reflection.Emit; |
34 | using System.Runtime.Serialization; | ||
35 | using System.Text; | 34 | using System.Text; |
36 | using System.Threading; | 35 | using System.Threading; |
37 | 36 | ||
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs index d9c578a..1cf1ad1 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs | |||
@@ -78,9 +78,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
78 | if (stackSize < 16384) stackSize = 16384; | 78 | if (stackSize < 16384) stackSize = 16384; |
79 | if (heapSize < 16384) heapSize = 16384; | 79 | if (heapSize < 16384) heapSize = 16384; |
80 | 80 | ||
81 | /* | 81 | // Save all call parameters in instance vars for easy access. |
82 | * Save all call parameters in instance vars for easy access. | ||
83 | */ | ||
84 | m_Engine = engine; | 82 | m_Engine = engine; |
85 | m_ScriptBasePath = scriptBasePath; | 83 | m_ScriptBasePath = scriptBasePath; |
86 | m_StackSize = stackSize; | 84 | m_StackSize = stackSize; |
@@ -88,185 +86,167 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
88 | m_CompilerErrors = errors; | 86 | m_CompilerErrors = errors; |
89 | m_StateFileName = GetStateFileName(scriptBasePath, m_ItemID); | 87 | m_StateFileName = GetStateFileName(scriptBasePath, m_ItemID); |
90 | 88 | ||
91 | /* | 89 | // Not in any XMRInstQueue. |
92 | * Not in any XMRInstQueue. | ||
93 | */ | ||
94 | m_NextInst = this; | 90 | m_NextInst = this; |
95 | m_PrevInst = this; | 91 | m_PrevInst = this; |
96 | 92 | ||
97 | /* | 93 | // Set up list of API calls it has available. |
98 | * Set up list of API calls it has available. | 94 | // This also gets the API modules ready to accept setup data, such as |
99 | * This also gets the API modules ready to accept setup data, such as | 95 | // active listeners being restored. |
100 | * active listeners being restored. | ||
101 | */ | ||
102 | IScriptApi scriptApi; | 96 | IScriptApi scriptApi; |
103 | ApiManager am = new ApiManager(); | 97 | ApiManager am = new ApiManager(); |
104 | foreach (string api in am.GetApis()) | 98 | foreach (string api in am.GetApis()) |
105 | { | 99 | { |
106 | /* | 100 | // Instantiate the API for this script instance. |
107 | * Instantiate the API for this script instance. | ||
108 | */ | ||
109 | if (api != "LSL") { | 101 | if (api != "LSL") { |
110 | scriptApi = am.CreateApi(api); | 102 | scriptApi = am.CreateApi(api); |
111 | } else { | 103 | } else { |
112 | scriptApi = m_XMRLSLApi = new XMRLSL_Api(); | 104 | scriptApi = m_XMRLSLApi = new XMRLSL_Api(); |
113 | } | 105 | } |
114 | 106 | ||
115 | /* | 107 | // Connect it up to the instance. |
116 | * Connect it up to the instance. | ||
117 | */ | ||
118 | InitScriptApi (engine, api, scriptApi); | 108 | InitScriptApi (engine, api, scriptApi); |
119 | } | 109 | } |
120 | 110 | ||
121 | m_XMRLSLApi.InitXMRLSLApi(this); | 111 | m_XMRLSLApi.InitXMRLSLApi(this); |
122 | 112 | ||
123 | /* | 113 | // Get object loaded, compiling script and reading .state file as |
124 | * Get object loaded, compiling script and reading .state file as | 114 | // necessary to restore the state. |
125 | * necessary to restore the state. | ||
126 | */ | ||
127 | suspendOnCheckRunHold = true; | 115 | suspendOnCheckRunHold = true; |
128 | InstantiateScript(); | 116 | InstantiateScript(); |
129 | m_SourceCode = null; | 117 | m_SourceCode = null; |
130 | if (m_ObjCode == null) throw new ArgumentNullException ("m_ObjCode"); | 118 | if (m_ObjCode == null) throw new ArgumentNullException ("m_ObjCode"); |
131 | if (m_ObjCode.scriptEventHandlerTable == null) { | 119 | if (m_ObjCode.scriptEventHandlerTable == null) |
132 | throw new ArgumentNullException ("m_ObjCode.scriptEventHandlerTable"); | 120 | throw new ArgumentNullException ("m_ObjCode.scriptEventHandlerTable"); |
133 | } | ||
134 | 121 | ||
135 | suspendOnCheckRunHold = false; | 122 | suspendOnCheckRunHold = false; |
136 | suspendOnCheckRunTemp = false; | 123 | suspendOnCheckRunTemp = false; |
137 | 124 | ||
138 | /* | 125 | // Declare which events the script's current state can handle. |
139 | * Declare which events the script's current state can handle. | ||
140 | */ | ||
141 | int eventMask = GetStateEventFlags(stateCode); | 126 | int eventMask = GetStateEventFlags(stateCode); |
142 | m_Part.SetScriptEvents(m_ItemID, eventMask); | 127 | m_Part.SetScriptEvents(m_ItemID, eventMask); |
143 | } | 128 | } |
144 | 129 | ||
145 | private void InitScriptApi (XMREngine engine, string api, IScriptApi scriptApi) | 130 | private void InitScriptApi (XMREngine engine, string api, IScriptApi scriptApi) |
146 | { | 131 | { |
147 | /* | 132 | // Set up m_ApiManager_<APINAME> = instance pointer. |
148 | * Set up m_ApiManager_<APINAME> = instance pointer. | ||
149 | */ | ||
150 | engine.m_XMRInstanceApiCtxFieldInfos[api].SetValue (this, scriptApi); | 133 | engine.m_XMRInstanceApiCtxFieldInfos[api].SetValue (this, scriptApi); |
151 | 134 | ||
152 | /* | 135 | // Initialize the API instance. |
153 | * Initialize the API instance. | ||
154 | */ | ||
155 | scriptApi.Initialize(m_Engine, m_Part, m_Item); | 136 | scriptApi.Initialize(m_Engine, m_Part, m_Item); |
156 | this.InitApi (api, scriptApi); | 137 | this.InitApi (api, scriptApi); |
157 | } | 138 | } |
158 | 139 | ||
159 | 140 | /* | |
160 | // Get script object code loaded in memory and all ready to run, | 141 | * Get script object code loaded in memory and all ready to run, |
161 | // ready to resume it from where the .state file says it was last | 142 | * ready to resume it from where the .state file says it was last |
143 | */ | ||
162 | private void InstantiateScript() | 144 | private void InstantiateScript() |
163 | { | 145 | { |
164 | bool compiledIt = false; | 146 | bool compiledIt = false; |
165 | ScriptObjCode objCode; | 147 | ScriptObjCode objCode; |
166 | 148 | ||
167 | /* | 149 | // If source code string is empty, use the asset ID as the object file name. |
168 | * If source code string is empty, use the asset ID as the object file name. | 150 | // Allow lines of // comments at the beginning (for such as engine selection). |
169 | * Allow lines of // comments at the beginning (for such as engine selection). | ||
170 | */ | ||
171 | int i, j, len; | 151 | int i, j, len; |
172 | if (m_SourceCode == null) m_SourceCode = String.Empty; | 152 | if (m_SourceCode == null) m_SourceCode = String.Empty; |
173 | for (len = m_SourceCode.Length; len > 0; -- len) { | 153 | for (len = m_SourceCode.Length; len > 0; --len) |
174 | if (m_SourceCode[len-1] > ' ') break; | 154 | { |
155 | if (m_SourceCode[len-1] > ' ') | ||
156 | break; | ||
175 | } | 157 | } |
176 | for (i = 0; i < len; i ++) { | 158 | for (i = 0; i < len; i ++) |
159 | { | ||
177 | char c = m_SourceCode[i]; | 160 | char c = m_SourceCode[i]; |
178 | if (c <= ' ') continue; | 161 | if (c <= ' ') |
179 | if (c != '/') break; | 162 | continue; |
180 | if ((i + 1 >= len) || (m_SourceCode[i+1] != '/')) break; | 163 | if (c != '/') |
164 | break; | ||
165 | if ((i + 1 >= len) || (m_SourceCode[i+1] != '/')) | ||
166 | break; | ||
181 | i = m_SourceCode.IndexOf ('\n', i); | 167 | i = m_SourceCode.IndexOf ('\n', i); |
182 | if (i < 0) i = len - 1; | 168 | if (i < 0) |
169 | i = len - 1; | ||
183 | } | 170 | } |
184 | if ((i >= len) || !m_Engine.m_UseSourceHashCode) { | 171 | if ((i >= len) || !m_Engine.m_UseSourceHashCode) |
185 | 172 | { | |
186 | /* | 173 | // Source consists of nothing but // comments and whitespace, |
187 | * Source consists of nothing but // comments and whitespace, | 174 | // or we are being forced to use the asset-id as the key, to |
188 | * or we are being forced to use the asset-id as the key, to | 175 | // open an already existing object code file. |
189 | * open an already existing object code file. | ||
190 | */ | ||
191 | m_ScriptObjCodeKey = m_Item.AssetID.ToString (); | 176 | m_ScriptObjCodeKey = m_Item.AssetID.ToString (); |
192 | if (i >= len) m_SourceCode = ""; | 177 | if (i >= len) |
193 | } else { | 178 | m_SourceCode = ""; |
194 | 179 | } | |
195 | /* | 180 | else |
196 | * Make up dictionary key for the object code. | 181 | { |
197 | * Use the same object code for identical source code | 182 | // Make up dictionary key for the object code. |
198 | * regardless of asset ID, so we don't care if they | 183 | // Use the same object code for identical source code |
199 | * copy scripts or not. | 184 | // regardless of asset ID, so we don't care if they |
200 | */ | 185 | // copy scripts or not. |
201 | byte[] scbytes = System.Text.Encoding.UTF8.GetBytes (m_SourceCode); | 186 | byte[] scbytes = System.Text.Encoding.UTF8.GetBytes (m_SourceCode); |
202 | StringBuilder sb = new StringBuilder ((256 + 5) / 6); | 187 | StringBuilder sb = new StringBuilder ((256 + 5) / 6); |
203 | ByteArrayToSixbitStr (sb, System.Security.Cryptography.SHA256.Create ().ComputeHash (scbytes)); | 188 | ByteArrayToSixbitStr (sb, System.Security.Cryptography.SHA256.Create ().ComputeHash (scbytes)); |
204 | m_ScriptObjCodeKey = sb.ToString (); | 189 | m_ScriptObjCodeKey = sb.ToString (); |
205 | 190 | ||
206 | /* | 191 | // But source code can be just a sixbit string itself |
207 | * But source code can be just a sixbit string itself | 192 | // that identifies an already existing object code file. |
208 | * that identifies an already existing object code file. | 193 | if (len - i == m_ScriptObjCodeKey.Length) |
209 | */ | 194 | { |
210 | if (len - i == m_ScriptObjCodeKey.Length) { | 195 | for (j = len; -- j >= i;) |
211 | for (j = len; -- j >= i;) { | 196 | { |
212 | if (sixbit.IndexOf (m_SourceCode[j]) < 0) break; | 197 | if (sixbit.IndexOf (m_SourceCode[j]) < 0) |
198 | break; | ||
213 | } | 199 | } |
214 | if (j < i) { | 200 | if (j < i) |
201 | { | ||
215 | m_ScriptObjCodeKey = m_SourceCode.Substring (i, len - i); | 202 | m_ScriptObjCodeKey = m_SourceCode.Substring (i, len - i); |
216 | m_SourceCode = ""; | 203 | m_SourceCode = ""; |
217 | } | 204 | } |
218 | } | 205 | } |
219 | } | 206 | } |
220 | 207 | ||
221 | /* | 208 | // There may already be an ScriptObjCode struct in memory that |
222 | * There may already be an ScriptObjCode struct in memory that | 209 | // we can use. If not, try to compile it. |
223 | * we can use. If not, try to compile it. | 210 | lock (m_CompileLock) |
224 | */ | 211 | { |
225 | lock (m_CompileLock) { | 212 | if (!m_CompiledScriptObjCode.TryGetValue (m_ScriptObjCodeKey, out objCode) || m_ForceRecomp) |
226 | if (!m_CompiledScriptObjCode.TryGetValue (m_ScriptObjCodeKey, out objCode) || m_ForceRecomp) { | 213 | { |
227 | objCode = TryToCompile (); | 214 | objCode = TryToCompile (); |
228 | compiledIt = true; | 215 | compiledIt = true; |
229 | } | 216 | } |
230 | 217 | ||
231 | /* | 218 | // Loaded successfully, increment reference count. |
232 | * Loaded successfully, increment reference count. | 219 | |
233 | * | 220 | // If we just compiled it though, reset count to 0 first as |
234 | * If we just compiled it though, reset count to 0 first as | 221 | // this is the one-and-only existance of this objCode struct, |
235 | * this is the one-and-only existance of this objCode struct, | 222 | // and we want any old ones for this source code to be garbage |
236 | * and we want any old ones for this source code to be garbage | 223 | // collected. |
237 | * collected. | 224 | |
238 | */ | 225 | if (compiledIt) |
239 | if (compiledIt) { | 226 | { |
240 | m_CompiledScriptObjCode[m_ScriptObjCodeKey] = objCode; | 227 | m_CompiledScriptObjCode[m_ScriptObjCodeKey] = objCode; |
241 | objCode.refCount = 0; | 228 | objCode.refCount = 0; |
242 | } | 229 | } |
243 | objCode.refCount ++; | 230 | objCode.refCount ++; |
244 | 231 | ||
245 | /* | 232 | // Now set up to decrement ref count on dispose. |
246 | * Now set up to decrement ref count on dispose. | ||
247 | */ | ||
248 | m_ObjCode = objCode; | 233 | m_ObjCode = objCode; |
249 | } | 234 | } |
250 | 235 | ||
251 | try { | 236 | try |
252 | 237 | { | |
253 | /* | 238 | // Fill in script instance from object code |
254 | * Fill in script instance from object code | 239 | // Script instance is put in a "never-ever-has-run-before" state. |
255 | * Script instance is put in a "never-ever-has-run-before" state. | ||
256 | */ | ||
257 | LoadObjCode(); | 240 | LoadObjCode(); |
258 | 241 | ||
259 | /* | 242 | // Fill in script intial state |
260 | * Fill in script intial state | 243 | // - either as loaded from a .state file |
261 | * - either as loaded from a .state file | 244 | // - or initial default state_entry() event |
262 | * - or initial default state_entry() event | ||
263 | */ | ||
264 | LoadInitialState(); | 245 | LoadInitialState(); |
265 | } catch { | 246 | } |
266 | 247 | catch | |
267 | /* | 248 | { |
268 | * If any error loading, decrement object code reference count. | 249 | // If any error loading, decrement object code reference count. |
269 | */ | ||
270 | DecObjCodeRefCount (); | 250 | DecObjCodeRefCount (); |
271 | throw; | 251 | throw; |
272 | } | 252 | } |
@@ -277,42 +257,41 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
277 | { | 257 | { |
278 | int bit = 0; | 258 | int bit = 0; |
279 | int val = 0; | 259 | int val = 0; |
280 | foreach (byte b in bytes) { | 260 | foreach (byte b in bytes) |
261 | { | ||
281 | val |= (int)((uint)b << bit); | 262 | val |= (int)((uint)b << bit); |
282 | bit += 8; | 263 | bit += 8; |
283 | while (bit >= 6) { | 264 | while (bit >= 6) |
265 | { | ||
284 | sb.Append (sixbit[val&63]); | 266 | sb.Append (sixbit[val&63]); |
285 | val >>= 6; | 267 | val >>= 6; |
286 | bit -= 6; | 268 | bit -= 6; |
287 | } | 269 | } |
288 | } | 270 | } |
289 | if (bit > 0) { | 271 | if (bit > 0) |
290 | sb.Append (sixbit[val&63]); | 272 | sb.Append (sixbit[val&63]); |
291 | } | ||
292 | } | 273 | } |
293 | 274 | ||
294 | // Try to create object code from source code | 275 | /* |
295 | // If error, just throw exception | 276 | * Try to create object code from source code |
277 | * If error, just throw exception | ||
278 | */ | ||
296 | private ScriptObjCode TryToCompile () | 279 | private ScriptObjCode TryToCompile () |
297 | { | 280 | { |
298 | m_CompilerErrors.Clear(); | 281 | m_CompilerErrors.Clear(); |
299 | 282 | ||
300 | /* | 283 | // If object file exists, create ScriptObjCode directly from that. |
301 | * If object file exists, create ScriptObjCode directly from that. | 284 | // Otherwise, compile the source to create object file then create |
302 | * Otherwise, compile the source to create object file then create | 285 | // ScriptObjCode from that. |
303 | * ScriptObjCode from that. | 286 | |
304 | */ | ||
305 | string assetID = m_Item.AssetID.ToString(); | 287 | string assetID = m_Item.AssetID.ToString(); |
306 | m_CameFrom = "asset://" + assetID; | 288 | m_CameFrom = "asset://" + assetID; |
307 | ScriptObjCode objCode = Compile (); | 289 | ScriptObjCode objCode = Compile (); |
308 | if (m_CompilerErrors.Count != 0) | 290 | if (m_CompilerErrors.Count != 0) |
309 | { | ||
310 | throw new Exception ("compilation errors"); | 291 | throw new Exception ("compilation errors"); |
311 | } | 292 | |
312 | if (objCode == null) | 293 | if (objCode == null) |
313 | { | ||
314 | throw new Exception ("compilation failed"); | 294 | throw new Exception ("compilation failed"); |
315 | } | ||
316 | 295 | ||
317 | return objCode; | 296 | return objCode; |
318 | } | 297 | } |
@@ -323,18 +302,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
323 | private string FetchSource (string cameFrom) | 302 | private string FetchSource (string cameFrom) |
324 | { | 303 | { |
325 | m_log.Debug ("[XMREngine]: fetching source " + cameFrom); | 304 | m_log.Debug ("[XMREngine]: fetching source " + cameFrom); |
326 | if (!cameFrom.StartsWith ("asset://")) { | 305 | if (!cameFrom.StartsWith ("asset://")) |
327 | throw new Exception ("unable to retrieve source from " + cameFrom); | 306 | throw new Exception ("unable to retrieve source from " + cameFrom); |
328 | } | 307 | |
329 | string assetID = cameFrom.Substring (8); | 308 | string assetID = cameFrom.Substring (8); |
330 | AssetBase asset = m_Engine.World.AssetService.Get(assetID); | 309 | AssetBase asset = m_Engine.World.AssetService.Get(assetID); |
331 | if (asset == null) { | 310 | if (asset == null) |
332 | throw new Exception ("source not found " + cameFrom); | 311 | throw new Exception ("source not found " + cameFrom); |
333 | } | 312 | |
334 | string source = Encoding.UTF8.GetString (asset.Data); | 313 | string source = Encoding.UTF8.GetString (asset.Data); |
335 | if (EmptySource (source)) { | 314 | if (EmptySource (source)) |
336 | throw new Exception ("fetched source empty " + cameFrom); | 315 | throw new Exception ("fetched source empty " + cameFrom); |
337 | } | 316 | |
338 | return source; | 317 | return source; |
339 | } | 318 | } |
340 | 319 | ||
@@ -344,53 +323,47 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
344 | */ | 323 | */ |
345 | private void LoadObjCode () | 324 | private void LoadObjCode () |
346 | { | 325 | { |
347 | /* | 326 | // Script must leave this much stack remaining on calls to CheckRun(). |
348 | * Script must leave this much stack remaining on calls to CheckRun(). | 327 | |
349 | */ | ||
350 | this.stackLimit = m_StackSize / 2; | 328 | this.stackLimit = m_StackSize / 2; |
351 | 329 | ||
352 | /* | 330 | // This is how many total heap bytes script is allowed to use. |
353 | * This is how many total heap bytes script is allowed to use. | ||
354 | */ | ||
355 | this.heapLimit = m_HeapSize; | 331 | this.heapLimit = m_HeapSize; |
356 | 332 | ||
357 | /* | 333 | // Allocate global variable arrays. |
358 | * Allocate global variable arrays. | ||
359 | */ | ||
360 | this.glblVars.AllocVarArrays (m_ObjCode.glblSizes); | 334 | this.glblVars.AllocVarArrays (m_ObjCode.glblSizes); |
361 | 335 | ||
362 | /* | 336 | // Script can handle these event codes. |
363 | * Script can handle these event codes. | ||
364 | */ | ||
365 | m_HaveEventHandlers = new bool[m_ObjCode.scriptEventHandlerTable.GetLength(1)]; | 337 | m_HaveEventHandlers = new bool[m_ObjCode.scriptEventHandlerTable.GetLength(1)]; |
366 | for (int i = m_ObjCode.scriptEventHandlerTable.GetLength(0); -- i >= 0;) { | 338 | for (int i = m_ObjCode.scriptEventHandlerTable.GetLength(0); -- i >= 0;) |
367 | for (int j = m_ObjCode.scriptEventHandlerTable.GetLength(1); -- j >= 0;) { | 339 | { |
368 | if (m_ObjCode.scriptEventHandlerTable[i,j] != null) { | 340 | for (int j = m_ObjCode.scriptEventHandlerTable.GetLength(1); -- j >= 0;) |
341 | { | ||
342 | if (m_ObjCode.scriptEventHandlerTable[i,j] != null) | ||
343 | { | ||
369 | m_HaveEventHandlers[j] = true; | 344 | m_HaveEventHandlers[j] = true; |
370 | } | 345 | } |
371 | } | 346 | } |
372 | } | 347 | } |
373 | 348 | ||
374 | /* | 349 | // Set up microthread object which actually calls the script event handler functions. |
375 | * Set up microthread object which actually calls the script event handler functions. | ||
376 | */ | ||
377 | this.microthread = (IScriptUThread)m_Engine.uThreadCtor.Invoke (new object[] { this }); | 350 | this.microthread = (IScriptUThread)m_Engine.uThreadCtor.Invoke (new object[] { this }); |
378 | } | 351 | } |
379 | 352 | ||
380 | // LoadInitialState() | 353 | /* |
381 | // if no state XML file exists for the asset, | 354 | * LoadInitialState() |
382 | // post initial default state events | 355 | * if no state XML file exists for the asset, |
383 | // else | 356 | * post initial default state events |
384 | // try to restore from .state file | 357 | * else |
385 | // If any error, throw exception | 358 | * try to restore from .state file |
386 | // | 359 | * If any error, throw exception |
360 | */ | ||
387 | private void LoadInitialState() | 361 | private void LoadInitialState() |
388 | { | 362 | { |
389 | /* | 363 | // If no .state file exists, start from default state |
390 | * If no .state file exists, start from default state | 364 | // Otherwise, read initial state from the .state file |
391 | * Otherwise, read initial state from the .state file | 365 | if (!File.Exists(m_StateFileName)) |
392 | */ | 366 | { |
393 | if (!File.Exists(m_StateFileName)) { | ||
394 | m_Running = true; // event processing is enabled | 367 | m_Running = true; // event processing is enabled |
395 | eventCode = ScriptEventCode.None; // not processing any event | 368 | eventCode = ScriptEventCode.None; // not processing any event |
396 | 369 | ||
@@ -401,7 +374,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
401 | PostEvent(new EventParams("state_entry", | 374 | PostEvent(new EventParams("state_entry", |
402 | zeroObjectArray, | 375 | zeroObjectArray, |
403 | zeroDetectParams)); | 376 | zeroDetectParams)); |
404 | } else { | 377 | } |
378 | else | ||
379 | { | ||
405 | FileStream fs = File.Open(m_StateFileName, | 380 | FileStream fs = File.Open(m_StateFileName, |
406 | FileMode.Open, | 381 | FileMode.Open, |
407 | FileAccess.Read); | 382 | FileAccess.Read); |
@@ -415,31 +390,29 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
415 | LoadScriptState(doc); | 390 | LoadScriptState(doc); |
416 | } | 391 | } |
417 | 392 | ||
418 | /* | 393 | // Post event(s) saying what caused the script to start. |
419 | * Post event(s) saying what caused the script to start. | 394 | if (m_PostOnRez) |
420 | */ | 395 | { |
421 | if (m_PostOnRez) { | ||
422 | PostEvent(new EventParams("on_rez", | 396 | PostEvent(new EventParams("on_rez", |
423 | new Object[] { m_StartParam }, | 397 | new Object[] { m_StartParam }, |
424 | zeroDetectParams)); | 398 | zeroDetectParams)); |
425 | } | 399 | } |
426 | 400 | ||
427 | switch (m_StateSource) { | 401 | switch (m_StateSource) |
428 | case StateSource.AttachedRez: { | 402 | { |
403 | case StateSource.AttachedRez: | ||
429 | // PostEvent(new EventParams("attach", | 404 | // PostEvent(new EventParams("attach", |
430 | // new object[] { m_Part.ParentGroup.AttachedAvatar.ToString() }, | 405 | // new object[] { m_Part.ParentGroup.AttachedAvatar.ToString() }, |
431 | // zeroDetectParams)); | 406 | // zeroDetectParams)); |
432 | break; | 407 | break; |
433 | } | ||
434 | 408 | ||
435 | case StateSource.PrimCrossing: { | 409 | case StateSource.PrimCrossing: |
436 | PostEvent(new EventParams("changed", | 410 | PostEvent(new EventParams("changed", |
437 | sbcCR, | 411 | sbcCR, |
438 | zeroDetectParams)); | 412 | zeroDetectParams)); |
439 | break; | 413 | break; |
440 | } | ||
441 | 414 | ||
442 | case StateSource.Teleporting: { | 415 | case StateSource.Teleporting: |
443 | PostEvent(new EventParams("changed", | 416 | PostEvent(new EventParams("changed", |
444 | sbcCR, | 417 | sbcCR, |
445 | zeroDetectParams)); | 418 | zeroDetectParams)); |
@@ -447,14 +420,12 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
447 | sbcCT, | 420 | sbcCT, |
448 | zeroDetectParams)); | 421 | zeroDetectParams)); |
449 | break; | 422 | break; |
450 | } | ||
451 | 423 | ||
452 | case StateSource.RegionStart: { | 424 | case StateSource.RegionStart: |
453 | PostEvent(new EventParams("changed", | 425 | PostEvent(new EventParams("changed", |
454 | sbcCRS, | 426 | sbcCRS, |
455 | zeroDetectParams)); | 427 | zeroDetectParams)); |
456 | break; | 428 | break; |
457 | } | ||
458 | } | 429 | } |
459 | } | 430 | } |
460 | 431 | ||
@@ -468,17 +439,19 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
468 | */ | 439 | */ |
469 | private void ErrorHandler(Token token, string message) | 440 | private void ErrorHandler(Token token, string message) |
470 | { | 441 | { |
471 | if (token != null) { | 442 | if (token != null) |
443 | { | ||
472 | string srcloc = token.SrcLoc; | 444 | string srcloc = token.SrcLoc; |
473 | if (srcloc.StartsWith (m_CameFrom)) { | 445 | if (srcloc.StartsWith (m_CameFrom)) |
474 | srcloc = srcloc.Substring (m_CameFrom.Length); | 446 | srcloc = srcloc.Substring (m_CameFrom.Length); |
475 | } | 447 | |
476 | m_CompilerErrors.Add(srcloc + " Error: " + message); | 448 | m_CompilerErrors.Add(srcloc + " Error: " + message); |
477 | } else if (message != null) { | 449 | } |
450 | else if (message != null) | ||
478 | m_CompilerErrors.Add("(0,0) Error: " + message); | 451 | m_CompilerErrors.Add("(0,0) Error: " + message); |
479 | } else { | 452 | |
453 | else | ||
480 | m_CompilerErrors.Add("(0,0) Error compiling, see exception in log"); | 454 | m_CompilerErrors.Add("(0,0) Error compiling, see exception in log"); |
481 | } | ||
482 | } | 455 | } |
483 | 456 | ||
484 | /** | 457 | /** |
@@ -503,28 +476,25 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
503 | 476 | ||
504 | // Everything we know is enclosed in <ScriptState>...</ScriptState> | 477 | // Everything we know is enclosed in <ScriptState>...</ScriptState> |
505 | XmlElement scriptStateN = (XmlElement)doc.SelectSingleNode("ScriptState"); | 478 | XmlElement scriptStateN = (XmlElement)doc.SelectSingleNode("ScriptState"); |
506 | if (scriptStateN == null) { | 479 | if (scriptStateN == null) |
507 | throw new Exception("no <ScriptState> tag"); | 480 | throw new Exception("no <ScriptState> tag"); |
508 | } | 481 | |
509 | string sen = scriptStateN.GetAttribute("Engine"); | 482 | string sen = scriptStateN.GetAttribute("Engine"); |
510 | if ((sen == null) || (sen != m_Engine.ScriptEngineName)) { | 483 | if ((sen == null) || (sen != m_Engine.ScriptEngineName)) |
511 | throw new Exception("<ScriptState> missing Engine=\"XMREngine\" attribute"); | 484 | throw new Exception("<ScriptState> missing Engine=\"XMREngine\" attribute"); |
512 | } | 485 | |
513 | 486 | ||
514 | // AssetID is unique for the script source text so make sure the | 487 | // AssetID is unique for the script source text so make sure the |
515 | // state file was written for that source file | 488 | // state file was written for that source file |
516 | string assetID = scriptStateN.GetAttribute("Asset"); | 489 | string assetID = scriptStateN.GetAttribute("Asset"); |
517 | if (assetID != m_Item.AssetID.ToString()) | 490 | if (assetID != m_Item.AssetID.ToString()) |
518 | { | ||
519 | throw new Exception("<ScriptState> assetID mismatch"); | 491 | throw new Exception("<ScriptState> assetID mismatch"); |
520 | } | ||
521 | 492 | ||
522 | // Also match the sourceHash in case script was | 493 | // Also match the sourceHash in case script was |
523 | // loaded via 'xmroption fetchsource' and has changed | 494 | // loaded via 'xmroption fetchsource' and has changed |
524 | string sourceHash = scriptStateN.GetAttribute ("SourceHash"); | 495 | string sourceHash = scriptStateN.GetAttribute ("SourceHash"); |
525 | if ((sourceHash == null) || (sourceHash != m_ObjCode.sourceHash)) { | 496 | if ((sourceHash == null) || (sourceHash != m_ObjCode.sourceHash)) |
526 | throw new Exception ("<ScriptState> SourceHash mismatch"); | 497 | throw new Exception ("<ScriptState> SourceHash mismatch"); |
527 | } | ||
528 | 498 | ||
529 | // Get various attributes | 499 | // Get various attributes |
530 | XmlElement runningN = (XmlElement)scriptStateN.SelectSingleNode("Running"); | 500 | XmlElement runningN = (XmlElement)scriptStateN.SelectSingleNode("Running"); |
@@ -549,8 +519,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
549 | Object[] pluginData = ExtractXMLObjectArray(pluginN, "plugin"); | 519 | Object[] pluginData = ExtractXMLObjectArray(pluginN, "plugin"); |
550 | 520 | ||
551 | // Script's global variables and stack contents | 521 | // Script's global variables and stack contents |
552 | XmlElement snapshotN = | 522 | XmlElement snapshotN = (XmlElement)scriptStateN.SelectSingleNode("Snapshot"); |
553 | (XmlElement)scriptStateN.SelectSingleNode("Snapshot"); | ||
554 | 523 | ||
555 | Byte[] data = Convert.FromBase64String(snapshotN.InnerText); | 524 | Byte[] data = Convert.FromBase64String(snapshotN.InnerText); |
556 | MemoryStream ms = new MemoryStream(); | 525 | MemoryStream ms = new MemoryStream(); |
@@ -561,18 +530,21 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
561 | 530 | ||
562 | // Restore event queues, preserving any events that queued | 531 | // Restore event queues, preserving any events that queued |
563 | // whilst we were restoring the state | 532 | // whilst we were restoring the state |
564 | lock (m_QueueLock) { | 533 | lock (m_QueueLock) |
534 | { | ||
565 | m_DetectParams = detParams; | 535 | m_DetectParams = detParams; |
566 | foreach (EventParams evt in m_EventQueue) { | 536 | foreach (EventParams evt in m_EventQueue) |
567 | eventQueue.AddLast (evt); | 537 | eventQueue.AddLast (evt); |
568 | } | 538 | |
569 | m_EventQueue = eventQueue; | 539 | m_EventQueue = eventQueue; |
570 | for (int i = m_EventCounts.Length; -- i >= 0;) m_EventCounts[i] = 0; | 540 | for (int i = m_EventCounts.Length; -- i >= 0;) |
541 | m_EventCounts[i] = 0; | ||
542 | |||
571 | foreach (EventParams evt in m_EventQueue) | 543 | foreach (EventParams evt in m_EventQueue) |
572 | { | 544 | { |
573 | ScriptEventCode eventCode = (ScriptEventCode)Enum.Parse (typeof (ScriptEventCode), | 545 | ScriptEventCode eventCode = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), |
574 | evt.EventName); | 546 | evt.EventName); |
575 | m_EventCounts[(int)eventCode] ++; | 547 | m_EventCounts[(int)eventCode]++; |
576 | } | 548 | } |
577 | } | 549 | } |
578 | 550 | ||
@@ -594,7 +566,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
594 | private LinkedList<EventParams> RestoreEventQueue(XmlNode eventsN) | 566 | private LinkedList<EventParams> RestoreEventQueue(XmlNode eventsN) |
595 | { | 567 | { |
596 | LinkedList<EventParams> eventQueue = new LinkedList<EventParams>(); | 568 | LinkedList<EventParams> eventQueue = new LinkedList<EventParams>(); |
597 | if (eventsN != null) { | 569 | if (eventsN != null) |
570 | { | ||
598 | XmlNodeList eventL = eventsN.SelectNodes("Event"); | 571 | XmlNodeList eventL = eventsN.SelectNodes("Event"); |
599 | foreach (XmlNode evnt in eventL) | 572 | foreach (XmlNode evnt in eventL) |
600 | { | 573 | { |
@@ -629,8 +602,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
629 | XmlNodeList detectL = detectedN.SelectNodes("DetectParams"); | 602 | XmlNodeList detectL = detectedN.SelectNodes("DetectParams"); |
630 | 603 | ||
631 | DetectParams detprm = new DetectParams(); | 604 | DetectParams detprm = new DetectParams(); |
632 | foreach (XmlNode detxml in detectL) { | 605 | foreach (XmlNode detxml in detectL) |
633 | try { | 606 | { |
607 | try | ||
608 | { | ||
634 | detprm.Group = new UUID(detxml.Attributes.GetNamedItem("group").Value); | 609 | detprm.Group = new UUID(detxml.Attributes.GetNamedItem("group").Value); |
635 | detprm.Key = new UUID(detxml.Attributes.GetNamedItem("key").Value); | 610 | detprm.Key = new UUID(detxml.Attributes.GetNamedItem("key").Value); |
636 | detprm.Owner = new UUID(detxml.Attributes.GetNamedItem("owner").Value); | 611 | detprm.Owner = new UUID(detxml.Attributes.GetNamedItem("owner").Value); |
@@ -648,7 +623,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
648 | 623 | ||
649 | detected.Add(detprm); | 624 | detected.Add(detprm); |
650 | detprm = new DetectParams(); | 625 | detprm = new DetectParams(); |
651 | } catch (Exception e) { | 626 | } |
627 | catch (Exception e) | ||
628 | { | ||
652 | m_log.Warn("[XMREngine]: RestoreDetectParams bad XML: " + detxml.ToString()); | 629 | m_log.Warn("[XMREngine]: RestoreDetectParams bad XML: " + detxml.ToString()); |
653 | m_log.Warn("[XMREngine]: ... " + e.ToString()); | 630 | m_log.Warn("[XMREngine]: ... " + e.ToString()); |
654 | } | 631 | } |
@@ -670,9 +647,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
670 | 647 | ||
671 | XmlNodeList itemL = parent.SelectNodes(tag); | 648 | XmlNodeList itemL = parent.SelectNodes(tag); |
672 | foreach (XmlNode item in itemL) | 649 | foreach (XmlNode item in itemL) |
673 | { | ||
674 | olist.Add(ExtractXMLObjectValue(item)); | 650 | olist.Add(ExtractXMLObjectValue(item)); |
675 | } | ||
676 | 651 | ||
677 | return olist.ToArray(); | 652 | return olist.ToArray(); |
678 | } | 653 | } |
@@ -682,9 +657,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
682 | string itemType = item.Attributes.GetNamedItem("type").Value; | 657 | string itemType = item.Attributes.GetNamedItem("type").Value; |
683 | 658 | ||
684 | if (itemType == "list") | 659 | if (itemType == "list") |
685 | { | ||
686 | return new LSL_List(ExtractXMLObjectArray(item, "item")); | 660 | return new LSL_List(ExtractXMLObjectArray(item, "item")); |
687 | } | ||
688 | 661 | ||
689 | if (itemType == "OpenMetaverse.UUID") | 662 | if (itemType == "OpenMetaverse.UUID") |
690 | { | 663 | { |
@@ -701,9 +674,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
701 | string assembly = itemType + ", OpenSim.Region.ScriptEngine.Shared"; | 674 | string assembly = itemType + ", OpenSim.Region.ScriptEngine.Shared"; |
702 | itemT = Type.GetType(assembly); | 675 | itemT = Type.GetType(assembly); |
703 | if (itemT == null) | 676 | if (itemT == null) |
704 | { | ||
705 | return null; | 677 | return null; |
706 | } | 678 | |
707 | return Activator.CreateInstance(itemT, args); | 679 | return Activator.CreateInstance(itemT, args); |
708 | } | 680 | } |
709 | 681 | ||
@@ -724,77 +696,82 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
724 | miehstream = stream; | 696 | miehstream = stream; |
725 | 697 | ||
726 | XMRScriptThread cst = XMRScriptThread.CurrentScriptThread (); | 698 | XMRScriptThread cst = XMRScriptThread.CurrentScriptThread (); |
727 | if (cst != null) { | 699 | if (cst != null) |
728 | 700 | { | |
729 | // in case we are getting called inside some LSL Api function | 701 | // in case we are getting called inside some LSL Api function |
730 | MigrateInEventHandlerThread (); | 702 | MigrateInEventHandlerThread (); |
731 | } else { | 703 | } |
732 | 704 | else | |
705 | { | ||
733 | // some other thread, do migration via a script thread | 706 | // some other thread, do migration via a script thread |
734 | lock (XMRScriptThread.m_WakeUpLock) { | 707 | lock (XMRScriptThread.m_WakeUpLock) |
708 | { | ||
735 | m_Engine.m_ThunkQueue.Enqueue (this.MigrateInEventHandlerThread); | 709 | m_Engine.m_ThunkQueue.Enqueue (this.MigrateInEventHandlerThread); |
736 | } | 710 | } |
737 | XMRScriptThread.WakeUpOne (); | 711 | XMRScriptThread.WakeUpOne (); |
738 | 712 | ||
739 | // wait for it to complete | 713 | // wait for it to complete |
740 | lock (miehdone) { | 714 | lock (miehdone) |
741 | while (miehstream != null) { | 715 | { |
742 | Monitor.Wait (miehdone); | 716 | while (miehstream != null) |
743 | } | 717 | Monitor.Wait(miehdone); |
744 | } | 718 | } |
745 | } | 719 | } |
746 | 720 | ||
747 | // maybe it threw up | 721 | // maybe it threw up |
748 | if (miehexcep != null) throw miehexcep; | 722 | if (miehexcep != null) |
723 | throw miehexcep; | ||
749 | } | 724 | } |
725 | |||
750 | private Exception miehexcep; | 726 | private Exception miehexcep; |
751 | private object miehdone = new object (); | 727 | private object miehdone = new object (); |
752 | private Stream miehstream; | 728 | private Stream miehstream; |
753 | private void MigrateInEventHandlerThread () | 729 | private void MigrateInEventHandlerThread () |
754 | { | 730 | { |
755 | try { | 731 | try |
732 | { | ||
756 | int mv = miehstream.ReadByte (); | 733 | int mv = miehstream.ReadByte (); |
757 | if (mv != migrationVersion) { | 734 | if (mv != migrationVersion) |
758 | throw new Exception ("incoming migration version " + mv + " but accept only " + migrationVersion); | 735 | throw new Exception ("incoming migration version " + mv + " but accept only " + migrationVersion); |
759 | } | 736 | |
760 | miehstream.ReadByte (); // ignored | 737 | miehstream.ReadByte (); // ignored |
761 | 738 | ||
762 | /* | 739 | // Restore script variables and stack and other state from stream. |
763 | * Restore script variables and stack and other state from stream. | 740 | // And it also marks us busy (by setting this.eventCode) so we can't be |
764 | * And it also marks us busy (by setting this.eventCode) so we can't be | 741 | // started again and this event lost. |
765 | * started again and this event lost. | 742 | |
766 | */ | ||
767 | BinaryReader br = new BinaryReader (miehstream); | 743 | BinaryReader br = new BinaryReader (miehstream); |
768 | this.MigrateIn (br); | 744 | this.MigrateIn (br); |
769 | 745 | ||
770 | /* | 746 | // If eventCode is None, it means the script was idle when migrated. |
771 | * If eventCode is None, it means the script was idle when migrated. | 747 | |
772 | */ | 748 | if (this.eventCode != ScriptEventCode.None) |
773 | if (this.eventCode != ScriptEventCode.None) { | 749 | { |
774 | 750 | // So microthread.Start() calls XMRScriptUThread.Main() which calls the | |
775 | /* | 751 | // event handler function. The event handler function sees the stack |
776 | * So microthread.Start() calls XMRScriptUThread.Main() which calls the | 752 | // frames in this.stackFrames and restores its args and locals, then calls |
777 | * event handler function. The event handler function sees the stack | 753 | // whatever it was calling when the snapshot was taken. That function also |
778 | * frames in this.stackFrames and restores its args and locals, then calls | 754 | // sees this.stackFrames and restores its args and locals, and so on... |
779 | * whatever it was calling when the snapshot was taken. That function also | 755 | // Eventually it gets to the point of calling CheckRun() which sees we are |
780 | * sees this.stackFrames and restores its args and locals, and so on... | 756 | // doing a restore and it suspends, returning here with the microthread |
781 | * Eventually it gets to the point of calling CheckRun() which sees we are | 757 | // stack all restored. It shouldn't ever throw an exception. |
782 | * doing a restore and it suspends, returning here with the microthread | 758 | |
783 | * stack all restored. It shouldn't ever throw an exception. | ||
784 | */ | ||
785 | this.stackFramesRestored = false; | 759 | this.stackFramesRestored = false; |
786 | Exception te = microthread.StartEx (); | 760 | Exception te = microthread.StartEx (); |
787 | if (te != null) throw te; | 761 | if (te != null) throw te; |
788 | if (!this.stackFramesRestored) throw new Exception ("migrate in did not complete"); | 762 | if (!this.stackFramesRestored) |
763 | throw new Exception ("migrate in did not complete"); | ||
789 | } | 764 | } |
790 | } catch (Exception e) { | 765 | } |
766 | catch (Exception e) | ||
767 | { | ||
791 | miehexcep = e; | 768 | miehexcep = e; |
792 | } finally { | 769 | } |
793 | 770 | finally | |
794 | /* | 771 | { |
795 | * Wake the MigrateInEventHandler() method above. | 772 | // Wake the MigrateInEventHandler() method above. |
796 | */ | 773 | lock (miehdone) |
797 | lock (miehdone) { | 774 | { |
798 | miehstream = null; | 775 | miehstream = null; |
799 | Monitor.Pulse (miehdone); | 776 | Monitor.Pulse (miehdone); |
800 | } | 777 | } |
@@ -807,67 +784,67 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
807 | */ | 784 | */ |
808 | public string CheckFetchbinaryAllowed () | 785 | public string CheckFetchbinaryAllowed () |
809 | { | 786 | { |
810 | string ownerPerm = m_Engine.Config.GetString ("Allow_fetchbinary", ""); | 787 | string ownerPerm = m_Engine.Config.GetString ("Allow_fetchbinary", ""); |
811 | UUID ownerID = m_Item.OwnerID; | 788 | UUID ownerID = m_Item.OwnerID; |
812 | string[] ids = ownerPerm.Split (new char[] { ',' }); | 789 | string[] ids = ownerPerm.Split (new char[] { ',' }); |
813 | foreach (string id in ids) { | 790 | foreach (string id in ids) |
814 | string curuc = id.Trim ().ToUpperInvariant (); | 791 | { |
792 | string curuc = id.Trim().ToUpperInvariant(); | ||
815 | 793 | ||
816 | switch (curuc) { | 794 | switch (curuc) |
817 | case "ESTATE_MANAGER": { | 795 | { |
796 | case "ESTATE_MANAGER": | ||
818 | if (m_Engine.m_Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner (ownerID) && | 797 | if (m_Engine.m_Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner (ownerID) && |
819 | (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner != ownerID)) { | 798 | (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner != ownerID)) |
820 | return null; | 799 | return null; |
821 | } | 800 | |
822 | break; | 801 | break; |
823 | } | ||
824 | 802 | ||
825 | case "ESTATE_OWNER": { | 803 | case "ESTATE_OWNER": |
826 | if (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner == ownerID) { | 804 | if (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner == ownerID) |
827 | return null; | 805 | return null; |
828 | } | 806 | |
829 | break; | 807 | break; |
830 | } | ||
831 | 808 | ||
832 | case "PARCEL_GROUP_MEMBER": { | 809 | case "PARCEL_GROUP_MEMBER": |
833 | ILandObject land = m_Engine.m_Scene.LandChannel.GetLandObject (m_Part.AbsolutePosition); | 810 | ILandObject land = m_Engine.m_Scene.LandChannel.GetLandObject (m_Part.AbsolutePosition); |
834 | if (land.LandData.GroupID == m_Item.GroupID && land.LandData.GroupID != UUID.Zero) { | 811 | if (land.LandData.GroupID == m_Item.GroupID && land.LandData.GroupID != UUID.Zero) |
835 | return null; | 812 | return null; |
836 | } | 813 | |
837 | break; | 814 | break; |
838 | } | ||
839 | 815 | ||
840 | case "PARCEL_OWNER": { | 816 | case "PARCEL_OWNER": |
841 | ILandObject land = m_Engine.m_Scene.LandChannel.GetLandObject (m_Part.AbsolutePosition); | 817 | ILandObject Oland = m_Engine.m_Scene.LandChannel.GetLandObject (m_Part.AbsolutePosition); |
842 | if (land.LandData.OwnerID == ownerID) { | 818 | if (Oland.LandData.OwnerID == ownerID) |
843 | return null; | 819 | return null; |
844 | } | 820 | |
845 | break; | 821 | break; |
846 | } | ||
847 | 822 | ||
848 | case "TRUE": { | 823 | case "TRUE": |
849 | return null; | 824 | return null; |
850 | } | ||
851 | 825 | ||
852 | default: { | 826 | default: |
853 | UUID uuid; | 827 | UUID uuid; |
854 | if (UUID.TryParse (curuc, out uuid)) { | 828 | if (UUID.TryParse (curuc, out uuid)) |
855 | if (uuid == ownerID) return null; | 829 | if (uuid == ownerID) return null; |
856 | } | 830 | |
857 | break; | 831 | break; |
858 | } | ||
859 | } | 832 | } |
860 | } | 833 | } |
861 | 834 | ||
862 | string creatorPerm = m_Engine.Config.GetString ("Creators_fetchbinary", ""); | 835 | string creatorPerm = m_Engine.Config.GetString ("Creators_fetchbinary", ""); |
863 | UUID creatorID = m_Item.CreatorID; | 836 | UUID creatorID = m_Item.CreatorID; |
864 | ids = creatorPerm.Split (new char[] { ',' }); | 837 | ids = creatorPerm.Split (new char[] { ',' }); |
865 | foreach (string id in ids) { | 838 | foreach (string id in ids) |
839 | { | ||
866 | string current = id.Trim (); | 840 | string current = id.Trim (); |
867 | UUID uuid; | 841 | UUID uuid; |
868 | if (UUID.TryParse (current, out uuid)) { | 842 | if (UUID.TryParse (current, out uuid)) |
869 | if (uuid != UUID.Zero) { | 843 | { |
870 | if (creatorID == uuid) return null; | 844 | if (uuid != UUID.Zero) |
845 | { | ||
846 | if (creatorID == uuid) | ||
847 | return null; | ||
871 | } | 848 | } |
872 | } | 849 | } |
873 | } | 850 | } |
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs index ddb3698..6470477 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs | |||
@@ -25,7 +25,6 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using Mono.Tasklets; | ||
29 | using OpenSim.Framework.Monitoring; | 28 | using OpenSim.Framework.Monitoring; |
30 | using System; | 29 | using System; |
31 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
@@ -70,7 +69,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
70 | private bool m_Exiting = false; | 69 | private bool m_Exiting = false; |
71 | private bool m_SuspendScriptThreadFlag = false; | 70 | private bool m_SuspendScriptThreadFlag = false; |
72 | private bool m_WakeUpThis = false; | 71 | private bool m_WakeUpThis = false; |
73 | private bool m_Continuations = false; | ||
74 | public DateTime m_LastRanAt = DateTime.MinValue; | 72 | public DateTime m_LastRanAt = DateTime.MinValue; |
75 | public int m_ScriptThreadTID = 0; | 73 | public int m_ScriptThreadTID = 0; |
76 | public long m_ScriptExecTime = 0; | 74 | public long m_ScriptExecTime = 0; |
@@ -78,15 +76,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
78 | private XMREngine engine; | 76 | private XMREngine engine; |
79 | public XMRInstance m_RunInstance = null; | 77 | public XMRInstance m_RunInstance = null; |
80 | 78 | ||
81 | public XMRScriptThread(XMREngine eng) | 79 | public XMRScriptThread(XMREngine eng, int i) |
82 | { | 80 | { |
83 | engine = eng; | 81 | engine = eng; |
84 | m_Continuations = engine.uThreadCtor.DeclaringType == typeof (ScriptUThread_Con); | 82 | if(i < 0) |
85 | // thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.BelowNormal); | 83 | thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.Normal); |
86 | thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.Normal); | 84 | else |
85 | thd = XMREngine.StartMyThread (RunScriptThread, "xmrengineExec" + i.ToString(), ThreadPriority.Normal); | ||
87 | lock (m_AllThreads) | 86 | lock (m_AllThreads) |
88 | m_AllThreads.Add (thd, this); | 87 | m_AllThreads.Add (thd, this); |
89 | |||
90 | } | 88 | } |
91 | 89 | ||
92 | public void SuspendThread() | 90 | public void SuspendThread() |
@@ -125,7 +123,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
125 | */ | 123 | */ |
126 | private void WakeUpScriptThread() | 124 | private void WakeUpScriptThread() |
127 | { | 125 | { |
128 | lock (m_WakeUpLock) { | 126 | lock (m_WakeUpLock) |
127 | { | ||
129 | m_WakeUpThis = true; | 128 | m_WakeUpThis = true; |
130 | Monitor.PulseAll (m_WakeUpLock); | 129 | Monitor.PulseAll (m_WakeUpLock); |
131 | } | 130 | } |
@@ -137,24 +136,22 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
137 | private void RunScriptThread() | 136 | private void RunScriptThread() |
138 | { | 137 | { |
139 | XMRInstance inst; | 138 | XMRInstance inst; |
140 | Mono.Tasklets.Continuation engstack = null; | ||
141 | if (m_Continuations) { | ||
142 | engstack = new Mono.Tasklets.Continuation (); | ||
143 | engstack.Mark (); | ||
144 | } | ||
145 | m_ScriptThreadTID = System.Threading.Thread.CurrentThread.ManagedThreadId; | 139 | m_ScriptThreadTID = System.Threading.Thread.CurrentThread.ManagedThreadId; |
146 | 140 | ||
147 | while (!m_Exiting) { | 141 | while (!m_Exiting) |
142 | { | ||
148 | XMREngine.UpdateMyThread (); | 143 | XMREngine.UpdateMyThread (); |
149 | 144 | ||
150 | /* | 145 | /* |
151 | * Handle 'xmr resume/suspend' commands. | 146 | * Handle 'xmr resume/suspend' commands. |
152 | */ | 147 | */ |
153 | if (m_SuspendScriptThreadFlag) { | 148 | if (m_SuspendScriptThreadFlag) |
149 | { | ||
154 | lock (m_WakeUpLock) { | 150 | lock (m_WakeUpLock) { |
155 | while (m_SuspendScriptThreadFlag && | 151 | while (m_SuspendScriptThreadFlag && |
156 | !m_Exiting && | 152 | !m_Exiting && |
157 | (engine.m_ThunkQueue.Count == 0)) { | 153 | (engine.m_ThunkQueue.Count == 0)) |
154 | { | ||
158 | Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); | 155 | Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); |
159 | XMREngine.UpdateMyThread (); | 156 | XMREngine.UpdateMyThread (); |
160 | } | 157 | } |
@@ -165,81 +162,72 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
165 | * Maybe there are some scripts waiting to be migrated in or out. | 162 | * Maybe there are some scripts waiting to be migrated in or out. |
166 | */ | 163 | */ |
167 | ThreadStart thunk = null; | 164 | ThreadStart thunk = null; |
168 | lock (m_WakeUpLock) { | 165 | lock (m_WakeUpLock) |
169 | if (engine.m_ThunkQueue.Count > 0) { | 166 | { |
167 | if (engine.m_ThunkQueue.Count > 0) | ||
170 | thunk = engine.m_ThunkQueue.Dequeue (); | 168 | thunk = engine.m_ThunkQueue.Dequeue (); |
171 | } | ||
172 | } | 169 | } |
173 | if (thunk != null) { | 170 | if (thunk != null) |
171 | { | ||
174 | inst = (XMRInstance)thunk.Target; | 172 | inst = (XMRInstance)thunk.Target; |
175 | if (m_Continuations && (inst.scrstack == null)) { | ||
176 | inst.engstack = engstack; | ||
177 | inst.scrstack = new Mono.Tasklets.Continuation (); | ||
178 | inst.scrstack.Mark (); | ||
179 | } | ||
180 | thunk (); | 173 | thunk (); |
181 | continue; | 174 | continue; |
182 | } | 175 | } |
183 | 176 | ||
184 | if (engine.m_StartProcessing) { | 177 | if (engine.m_StartProcessing) |
178 | { | ||
179 | // If event just queued to any idle scripts | ||
180 | // start them right away. But only start so | ||
181 | // many so we can make some progress on yield | ||
182 | // queue. | ||
185 | 183 | ||
186 | /* | ||
187 | * If event just queued to any idle scripts | ||
188 | * start them right away. But only start so | ||
189 | * many so we can make some progress on yield | ||
190 | * queue. | ||
191 | */ | ||
192 | int numStarts; | 184 | int numStarts; |
193 | for (numStarts = 5; -- numStarts >= 0;) { | 185 | for (numStarts = 5; -- numStarts >= 0;) |
194 | lock (engine.m_StartQueue) { | 186 | { |
187 | lock (engine.m_StartQueue) | ||
188 | { | ||
195 | inst = engine.m_StartQueue.RemoveHead(); | 189 | inst = engine.m_StartQueue.RemoveHead(); |
196 | } | 190 | } |
197 | if (inst == null) break; | 191 | if (inst == null) break; |
198 | if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); | 192 | if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); |
199 | if (m_Continuations && (inst.scrstack == null)) { | ||
200 | inst.engstack = engstack; | ||
201 | inst.scrstack = new Mono.Tasklets.Continuation (); | ||
202 | inst.scrstack.Mark (); | ||
203 | } | ||
204 | RunInstance (inst); | 193 | RunInstance (inst); |
205 | } | 194 | } |
206 | 195 | ||
207 | /* | 196 | // If there is something to run, run it |
208 | * If there is something to run, run it | 197 | // then rescan from the beginning in case |
209 | * then rescan from the beginning in case | 198 | // a lot of things have changed meanwhile. |
210 | * a lot of things have changed meanwhile. | 199 | // |
211 | * | 200 | // These are considered lower priority than |
212 | * These are considered lower priority than | 201 | // m_StartQueue as they have been taking at |
213 | * m_StartQueue as they have been taking at | 202 | // least one quantum of CPU time and event |
214 | * least one quantum of CPU time and event | 203 | // handlers are supposed to be quick. |
215 | * handlers are supposed to be quick. | 204 | |
216 | */ | 205 | lock (engine.m_YieldQueue) |
217 | lock (engine.m_YieldQueue) { | 206 | { |
218 | inst = engine.m_YieldQueue.RemoveHead(); | 207 | inst = engine.m_YieldQueue.RemoveHead(); |
219 | } | 208 | } |
220 | if (inst != null) { | 209 | if (inst != null) |
210 | { | ||
221 | if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state"); | 211 | if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state"); |
222 | RunInstance (inst); | 212 | RunInstance(inst); |
223 | numStarts = -1; | 213 | numStarts = -1; |
224 | } | 214 | } |
225 | 215 | ||
226 | /* | 216 | // If we left something dangling in the m_StartQueue or m_YieldQueue, go back to check it. |
227 | * If we left something dangling in the m_StartQueue or m_YieldQueue, go back to check it. | 217 | if (numStarts < 0) |
228 | */ | 218 | continue; |
229 | if (numStarts < 0) continue; | ||
230 | } | 219 | } |
231 | 220 | ||
232 | /* | 221 | // Nothing to do, sleep. |
233 | * Nothing to do, sleep. | 222 | |
234 | */ | 223 | lock (m_WakeUpLock) |
235 | lock (m_WakeUpLock) { | 224 | { |
236 | if (!m_WakeUpThis && (m_WakeUpOne <= 0) && !m_Exiting) { | 225 | if (!m_WakeUpThis && (m_WakeUpOne <= 0) && !m_Exiting) |
237 | Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); | 226 | Monitor.Wait(m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); |
238 | } | 227 | |
239 | m_WakeUpThis = false; | 228 | m_WakeUpThis = false; |
240 | if ((m_WakeUpOne > 0) && (-- m_WakeUpOne > 0)) { | 229 | if ((m_WakeUpOne > 0) && (-- m_WakeUpOne > 0)) |
241 | Monitor.Pulse (m_WakeUpLock); | 230 | Monitor.Pulse (m_WakeUpLock); |
242 | } | ||
243 | } | 231 | } |
244 | } | 232 | } |
245 | XMREngine.MyThreadExiting (); | 233 | XMREngine.MyThreadExiting (); |
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs index 2e290dd..74bba4f 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs | |||
@@ -25,31 +25,24 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using Mono.Tasklets; | ||
29 | using System; | 28 | using System; |
30 | using System.Collections.Generic; | ||
31 | using System.Reflection; | ||
32 | using System.Threading; | ||
33 | |||
34 | |||
35 | 29 | ||
36 | /***************************\ | 30 | /***************************\ |
37 | * Use standard C# code * | 31 | * Use standard C# code * |
38 | * - uses system threads * | 32 | * - uses stack smashing * |
39 | \***************************/ | 33 | \***************************/ |
40 | 34 | ||
41 | namespace OpenSim.Region.ScriptEngine.XMREngine { | 35 | namespace OpenSim.Region.ScriptEngine.XMREngine |
36 | { | ||
42 | 37 | ||
43 | public class ScriptUThread_Sys : IScriptUThread, IDisposable | 38 | public class ScriptUThread_Nul : IScriptUThread, IDisposable |
44 | { | 39 | { |
45 | private Exception except; | ||
46 | private int active; // -1: hibernating | 40 | private int active; // -1: hibernating |
47 | // 0: exited | 41 | // 0: exited |
48 | // 1: running | 42 | // 1: running |
49 | private object activeLock = new object (); | ||
50 | private XMRInstance instance; | 43 | private XMRInstance instance; |
51 | 44 | ||
52 | public ScriptUThread_Sys (XMRInstance instance) | 45 | public ScriptUThread_Nul (XMRInstance instance) |
53 | { | 46 | { |
54 | this.instance = instance; | 47 | this.instance = instance; |
55 | } | 48 | } |
@@ -63,31 +56,27 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { | |||
63 | */ | 56 | */ |
64 | public Exception StartEx () | 57 | public Exception StartEx () |
65 | { | 58 | { |
66 | lock (activeLock) { | 59 | // We should only be called when no event handler running. |
67 | 60 | if (active != 0) throw new Exception ("active=" + active); | |
68 | /* | 61 | |
69 | * We should only be called when script is inactive. | 62 | // Start script event handler from very beginning. |
70 | */ | 63 | active = 1; |
71 | if (active != 0) throw new Exception ("active=" + active); | 64 | Exception except = null; |
72 | 65 | instance.callMode = XMRInstance.CallMode_NORMAL; | |
73 | /* | 66 | try { |
74 | * Tell CallSEHThread() to run script event handler in a thread. | 67 | instance.CallSEH (); // run script event handler |
75 | */ | 68 | active = 0; |
76 | active = 1; | 69 | } catch (StackHibernateException) { |
77 | TredPoo.RunSomething (CallSEHThread); | 70 | if (instance.callMode != XMRInstance.CallMode_SAVE) { |
78 | 71 | throw new Exception ("callMode=" + instance.callMode); | |
79 | /* | ||
80 | * Wait for script to call Hiber() or for script to | ||
81 | * return back out to CallSEHThread(). | ||
82 | */ | ||
83 | while (active > 0) { | ||
84 | Monitor.Wait (activeLock); | ||
85 | } | 72 | } |
73 | active = -1; // it is hibernating, can be resumed | ||
74 | } catch (Exception e) { | ||
75 | active = 0; | ||
76 | except = e; // threw exception, save for Start()/Resume() | ||
86 | } | 77 | } |
87 | 78 | ||
88 | /* | 79 | // Return whether or not script threw an exception. |
89 | * Return whether or not script threw an exception. | ||
90 | */ | ||
91 | return except; | 80 | return except; |
92 | } | 81 | } |
93 | 82 | ||
@@ -98,31 +87,27 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { | |||
98 | */ | 87 | */ |
99 | public Exception ResumeEx () | 88 | public Exception ResumeEx () |
100 | { | 89 | { |
101 | lock (activeLock) { | 90 | // We should only be called when script is hibernating. |
102 | 91 | if (active >= 0) throw new Exception ("active=" + active); | |
103 | /* | 92 | |
104 | * We should only be called when script is hibernating. | 93 | // Resume script from captured stack. |
105 | */ | 94 | instance.callMode = XMRInstance.CallMode_RESTORE; |
106 | if (active >= 0) throw new Exception ("active=" + active); | 95 | instance.suspendOnCheckRunTemp = true; |
107 | 96 | Exception except = null; | |
108 | /* | 97 | try { |
109 | * Tell Hiber() to return back to script. | 98 | instance.CallSEH (); // run script event handler |
110 | */ | 99 | active = 0; |
111 | active = 1; | 100 | } catch (StackHibernateException) { |
112 | Monitor.PulseAll (activeLock); | 101 | if (instance.callMode != XMRInstance.CallMode_SAVE) { |
113 | 102 | throw new Exception ("callMode=" + instance.callMode); | |
114 | /* | ||
115 | * Wait for script to call Hiber() again or for script to | ||
116 | * return back out to CallSEHThread(). | ||
117 | */ | ||
118 | while (active > 0) { | ||
119 | Monitor.Wait (activeLock); | ||
120 | } | 103 | } |
104 | active = -1; | ||
105 | } catch (Exception e) { | ||
106 | active = 0; | ||
107 | except = e; // threw exception, save for Start()/Resume() | ||
121 | } | 108 | } |
122 | 109 | ||
123 | /* | 110 | // Return whether or not script threw an exception. |
124 | * Return whether or not script threw an exception. | ||
125 | */ | ||
126 | return except; | 111 | return except; |
127 | } | 112 | } |
128 | 113 | ||
@@ -131,241 +116,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { | |||
131 | * Terminate thread asap. | 116 | * Terminate thread asap. |
132 | */ | 117 | */ |
133 | public void Dispose () | 118 | public void Dispose () |
134 | { | ||
135 | lock (activeLock) { | ||
136 | instance = null; | ||
137 | Monitor.PulseAll (activeLock); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * @brief Determine if script is active. | ||
143 | * Returns: 0: nothing started or has returned | ||
144 | * Resume() must not be called | ||
145 | * Start() may be called | ||
146 | * Hiber() must not be called | ||
147 | * -1: thread has called Hiber() | ||
148 | * Resume() may be called | ||
149 | * Start() may be called | ||
150 | * Hiber() must not be called | ||
151 | * 1: thread is running | ||
152 | * Resume() must not be called | ||
153 | * Start() must not be called | ||
154 | * Hiber() may be called | ||
155 | */ | ||
156 | public int Active () | ||
157 | { | ||
158 | return active; | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * @brief This thread executes the script event handler code. | ||
163 | */ | ||
164 | private void CallSEHThread () | ||
165 | { | ||
166 | lock (activeLock) { | ||
167 | if (active <= 0) throw new Exception ("active=" + active); | ||
168 | |||
169 | except = null; // assume completion without exception | ||
170 | try { | ||
171 | instance.CallSEH (); // run script event handler | ||
172 | } catch (Exception e) { | ||
173 | except = e; // threw exception, save for Start()/Resume() | ||
174 | } | ||
175 | |||
176 | active = 0; // tell Start() or Resume() we're done | ||
177 | Monitor.PulseAll (activeLock); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /** | ||
182 | * @brief Called by the script event handler whenever it wants to hibernate. | ||
183 | */ | ||
184 | public void Hiber () | ||
185 | { | ||
186 | if (active <= 0) throw new Exception ("active=" + active); | ||
187 | |||
188 | // tell Start() or Resume() we are hibernating | ||
189 | active = -1; | ||
190 | Monitor.PulseAll (activeLock); | ||
191 | |||
192 | // wait for Resume() or Dispose() to be called | ||
193 | while ((active < 0) && (instance != null)) { | ||
194 | Monitor.Wait (activeLock); | ||
195 | } | ||
196 | |||
197 | // don't execute any more script code, just exit | ||
198 | if (instance == null) { | ||
199 | throw new AbortedByDisposeException (); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * @brief Number of remaining stack bytes. | ||
205 | */ | ||
206 | public int StackLeft () | ||
207 | { | ||
208 | return 0x7FFFFFFF; | ||
209 | } | ||
210 | |||
211 | public class AbortedByDisposeException : Exception, IXMRUncatchable { } | ||
212 | |||
213 | /** | ||
214 | * @brief Pool of threads that run script event handlers. | ||
215 | */ | ||
216 | private class TredPoo { | ||
217 | private static readonly TimeSpan idleTimeSpan = new TimeSpan (0, 0, 1, 0, 0); // 1 minute | ||
218 | |||
219 | private static int tredPooAvail = 0; | ||
220 | private static object tredPooLock = new object (); | ||
221 | private static Queue<ThreadStart> tredPooQueue = new Queue<ThreadStart> (); | ||
222 | |||
223 | /** | ||
224 | * @brief Queue a function for execution in a system thread. | ||
225 | */ | ||
226 | public static void RunSomething (ThreadStart entry) | ||
227 | { | ||
228 | lock (tredPooLock) { | ||
229 | tredPooQueue.Enqueue (entry); | ||
230 | Monitor.Pulse (tredPooLock); | ||
231 | if (tredPooAvail < tredPooQueue.Count) { | ||
232 | new TredPoo (); | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * @brief Start a new system thread. | ||
239 | * It will shortly attempt to dequeue work or if none, | ||
240 | * add itself to the available thread list. | ||
241 | */ | ||
242 | private TredPoo () | ||
243 | { | ||
244 | Thread thread = new Thread (Main); | ||
245 | thread.Name = "XMRUThread_sys"; | ||
246 | thread.IsBackground = true; | ||
247 | thread.Start (); | ||
248 | tredPooAvail ++; | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * @brief Executes items from the queue or waits a little while | ||
253 | * if nothing. If idle for a while, it exits. | ||
254 | */ | ||
255 | private void Main () | ||
256 | { | ||
257 | int first = 1; | ||
258 | ThreadStart entry; | ||
259 | while (true) { | ||
260 | lock (tredPooLock) { | ||
261 | tredPooAvail -= first; | ||
262 | first = 0; | ||
263 | while (tredPooQueue.Count <= 0) { | ||
264 | tredPooAvail ++; | ||
265 | bool keepgoing = Monitor.Wait (tredPooLock, idleTimeSpan); | ||
266 | -- tredPooAvail; | ||
267 | if (!keepgoing) return; | ||
268 | } | ||
269 | entry = tredPooQueue.Dequeue (); | ||
270 | } | ||
271 | entry (); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | |||
278 | |||
279 | |||
280 | /*************************************\ | ||
281 | * Use Mono.Tasklets.Continuations * | ||
282 | * - memcpy's stack * | ||
283 | \*************************************/ | ||
284 | |||
285 | namespace OpenSim.Region.ScriptEngine.XMREngine { | ||
286 | |||
287 | public partial class XMRInstance { | ||
288 | public Mono.Tasklets.Continuation engstack; | ||
289 | public Mono.Tasklets.Continuation scrstack; | ||
290 | } | ||
291 | |||
292 | public class ScriptUThread_Con : IScriptUThread, IDisposable | ||
293 | { | ||
294 | private XMRInstance instance; | ||
295 | |||
296 | public ScriptUThread_Con (XMRInstance instance) | ||
297 | { | ||
298 | this.instance = instance; | ||
299 | } | ||
300 | |||
301 | private const int SAVEENGINESTACK = 0; | ||
302 | private const int LOADENGINESTACK = 1; | ||
303 | private const int SAVESCRIPTSTACK = 2; | ||
304 | private const int LOADSCRIPTSTACK = 3; | ||
305 | |||
306 | private Exception except; | ||
307 | private int active; | ||
308 | |||
309 | /** | ||
310 | * @brief Start script event handler from the beginning. | ||
311 | * Return when either the script event handler completes | ||
312 | * or the script calls Hiber(). | ||
313 | * @returns null: script did not throw any exception so far | ||
314 | * else: script threw an exception | ||
315 | */ | ||
316 | public Exception StartEx () | ||
317 | { | ||
318 | /* | ||
319 | * Save engine stack so we know how to jump back to engine in case | ||
320 | * the script calls Hiber(). | ||
321 | */ | ||
322 | switch (instance.engstack.Store (SAVEENGINESTACK)) { | ||
323 | |||
324 | /* | ||
325 | * Engine stack has been saved, start running the event handler. | ||
326 | */ | ||
327 | case SAVEENGINESTACK: { | ||
328 | |||
329 | /* | ||
330 | * Run event handler according to stackFrames. | ||
331 | * In either case it is assumed that stateCode and eventCode | ||
332 | * indicate which event handler is to be called and that ehArgs | ||
333 | * points to the event handler argument list. | ||
334 | */ | ||
335 | active = 1; | ||
336 | except = null; | ||
337 | try { | ||
338 | instance.CallSEH (); | ||
339 | } catch (Exception e) { | ||
340 | except = e; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * We now want to return to the script engine. | ||
345 | * Setting active = 0 means the microthread has exited. | ||
346 | * We need to call engstack.Restore() in case the script called Hiber() | ||
347 | * anywhere, we want to return out the corresponding Restore() and not the | ||
348 | * Start(). | ||
349 | */ | ||
350 | active = 0; | ||
351 | instance.engstack.Restore (LOADENGINESTACK); | ||
352 | throw new Exception ("returned from Restore()"); | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Script called Hiber() somewhere so just return back out. | ||
357 | */ | ||
358 | case LOADENGINESTACK: { | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | default: throw new Exception ("bad engstack code"); | ||
363 | } | ||
364 | |||
365 | return except; | ||
366 | } | ||
367 | |||
368 | public void Dispose () | ||
369 | { } | 119 | { } |
370 | 120 | ||
371 | /** | 121 | /** |
@@ -389,75 +139,33 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { | |||
389 | } | 139 | } |
390 | 140 | ||
391 | /** | 141 | /** |
392 | * @brief Called by the script wherever it wants to hibernate. | 142 | * @brief Called by the script event handler whenever it wants to hibernate. |
393 | * So this means to save the scripts stack in 'instance.scrstack' then | ||
394 | * restore the engstack to cause us to return back to the engine. | ||
395 | */ | 143 | */ |
396 | public void Hiber () | 144 | public void Hiber () |
397 | { | 145 | { |
398 | /* | 146 | if (instance.callMode != XMRInstance.CallMode_NORMAL) { |
399 | * Save where we are in the script's code in 'instance.scrstack' | 147 | throw new Exception ("callMode=" + instance.callMode); |
400 | * so we can wake the script when Resume() is called. | ||
401 | */ | ||
402 | switch (instance.scrstack.Store (SAVESCRIPTSTACK)) { | ||
403 | |||
404 | /* | ||
405 | * Script's stack is now saved in 'instance.scrstack'. | ||
406 | * Reload the engine's stack from 'instance.engstack' and jump to it. | ||
407 | */ | ||
408 | case SAVESCRIPTSTACK: { | ||
409 | active = -1; | ||
410 | instance.engstack.Restore (LOADENGINESTACK); | ||
411 | throw new Exception ("returned from Restore()"); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Resume() was just called and we want to resume executing script code. | ||
416 | */ | ||
417 | case LOADSCRIPTSTACK: { | ||
418 | break; | ||
419 | } | ||
420 | |||
421 | default: throw new Exception ("bad scrstack code"); | ||
422 | } | 148 | } |
423 | } | ||
424 | 149 | ||
425 | /** | 150 | switch (active) { |
426 | * @brief We now want to run some more script code from where it last hibernated | ||
427 | * until it either finishes the script event handler or until the script | ||
428 | * calls Hiber() again. | ||
429 | */ | ||
430 | public Exception ResumeEx () | ||
431 | { | ||
432 | /* | ||
433 | * Save where we are in the engine's code in 'instance.engstack' | ||
434 | * so if the script calls Hiber() again or exits, we know how to get | ||
435 | * back to the engine. | ||
436 | */ | ||
437 | switch (instance.engstack.Store (SAVEENGINESTACK)) { | ||
438 | 151 | ||
439 | /* | 152 | // the stack has been restored as a result of calling ResumeEx() |
440 | * This is original call to Resume() from the engine, | 153 | // say the microthread is now active and resume processing |
441 | * jump to where we left off within Hiber(). | 154 | case -1: { |
442 | */ | ||
443 | case SAVEENGINESTACK: { | ||
444 | active = 1; | 155 | active = 1; |
445 | instance.scrstack.Restore (LOADSCRIPTSTACK); | 156 | return; |
446 | throw new Exception ("returned from Restore()"); | ||
447 | } | 157 | } |
448 | 158 | ||
449 | /* | 159 | // the script event handler wants to hibernate |
450 | * Script has called Hiber() again, so return back to | 160 | // capture stack frames and unwind to Start() or Resume() |
451 | * script engine code. | 161 | case 1: { |
452 | */ | 162 | instance.callMode = XMRInstance.CallMode_SAVE; |
453 | case LOADENGINESTACK: { | 163 | instance.stackFrames = null; |
454 | break; | 164 | throw new StackHibernateException (); |
455 | } | 165 | } |
456 | 166 | ||
457 | default: throw new Exception ("bad engstack code"); | 167 | default: throw new Exception ("active=" + active); |
458 | } | 168 | } |
459 | |||
460 | return except; | ||
461 | } | 169 | } |
462 | 170 | ||
463 | /** | 171 | /** |
@@ -467,91 +175,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { | |||
467 | { | 175 | { |
468 | return 0x7FFFFFFF; | 176 | return 0x7FFFFFFF; |
469 | } | 177 | } |
470 | } | ||
471 | } | ||
472 | |||
473 | |||
474 | |||
475 | /***********************************\ | ||
476 | * Use Mono.Tasklets.MMRUThreads * | ||
477 | * - switches stack pointer * | ||
478 | \***********************************/ | ||
479 | |||
480 | namespace OpenSim.Region.ScriptEngine.XMREngine { | ||
481 | |||
482 | public class ScriptUThread_MMR : IScriptUThread, IDisposable | ||
483 | { | ||
484 | private static Exception uthread_looked; | ||
485 | private static Type uttype; | ||
486 | private static Type uthread_entry; | ||
487 | private static MethodInfo uthread_dispose; | ||
488 | private static MethodInfo uthread_startex; | ||
489 | private static MethodInfo uthread_resumex; | ||
490 | private static MethodInfo uthread_suspend; | ||
491 | private static MethodInfo uthread_active; | ||
492 | private static MethodInfo uthread_stackleft; | ||
493 | |||
494 | public static Exception LoadMono () | ||
495 | { | ||
496 | if ((uthread_looked == null) && (uthread_stackleft == null)) { | ||
497 | try { | ||
498 | Assembly mt = Assembly.Load ("Mono.Tasklets"); | ||
499 | uttype = mt.GetType ("Mono.Tasklets.MMRUThread", true); | ||
500 | uthread_entry = mt.GetType ("Mono.Tasklets.MMRUThread+Entry", true); | ||
501 | |||
502 | uthread_dispose = uttype.GetMethod ("Dispose"); // no parameters, no return value | ||
503 | uthread_startex = uttype.GetMethod ("StartEx"); // takes uthread_entry delegate as parameter, returns exception | ||
504 | uthread_resumex = uttype.GetMethod ("ResumeEx"); // takes exception as parameter, returns exception | ||
505 | uthread_suspend = uttype.GetMethod ("Suspend", new Type[] { }); // no return value | ||
506 | uthread_active = uttype.GetMethod ("Active"); // no parameters, returns int | ||
507 | uthread_stackleft = uttype.GetMethod ("StackLeft"); // no parameters, returns IntPtr | ||
508 | } catch (Exception e) { | ||
509 | uthread_looked = new NotSupportedException ("'mmr' thread model requires patched mono", e); | ||
510 | } | ||
511 | } | ||
512 | return uthread_looked; | ||
513 | } | ||
514 | 178 | ||
515 | private static object[] resumex_args = new object[] { null }; | 179 | public class StackHibernateException : Exception, IXMRUncatchable { } |
516 | |||
517 | private object uthread; // type MMRUThread | ||
518 | private object[] startex_args = new object[1]; | ||
519 | |||
520 | public ScriptUThread_MMR (XMRInstance instance) | ||
521 | { | ||
522 | this.uthread = Activator.CreateInstance (uttype, new object[] { (IntPtr) instance.m_StackSize, instance.m_DescName }); | ||
523 | startex_args[0] = Delegate.CreateDelegate (uthread_entry, instance, "CallSEH"); | ||
524 | } | ||
525 | |||
526 | public void Dispose () | ||
527 | { | ||
528 | uthread_dispose.Invoke (uthread, null); | ||
529 | uthread = null; | ||
530 | } | ||
531 | |||
532 | public Exception StartEx () | ||
533 | { | ||
534 | return (Exception) uthread_startex.Invoke (uthread, startex_args); | ||
535 | } | ||
536 | |||
537 | public Exception ResumeEx () | ||
538 | { | ||
539 | return (Exception) uthread_resumex.Invoke (uthread, resumex_args); | ||
540 | } | ||
541 | |||
542 | public void Hiber () | ||
543 | { | ||
544 | uthread_suspend.Invoke (null, null); | ||
545 | } | ||
546 | |||
547 | public int Active () | ||
548 | { | ||
549 | return (int) uthread_active.Invoke (uthread, null); | ||
550 | } | ||
551 | |||
552 | public int StackLeft () | ||
553 | { | ||
554 | return (int) (IntPtr) uthread_stackleft.Invoke (null, null); | ||
555 | } | ||
556 | } | 180 | } |
557 | } | 181 | } |
182 | |||