aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XMREngine
diff options
context:
space:
mode:
authorUbitUmarov2018-02-07 10:26:20 +0000
committerUbitUmarov2018-02-07 10:26:20 +0000
commit53a910e3e5add262a4fee1f73aad7419f9d150b5 (patch)
treeed41e3a2014bbf5c7f1977279a16315be1aafed2 /OpenSim/Region/ScriptEngine/XMREngine
parentdue credits even if code goes away (diff)
downloadopensim-SC-53a910e3e5add262a4fee1f73aad7419f9d150b5.zip
opensim-SC-53a910e3e5add262a4fee1f73aad7419f9d150b5.tar.gz
opensim-SC-53a910e3e5add262a4fee1f73aad7419f9d150b5.tar.bz2
opensim-SC-53a910e3e5add262a4fee1f73aad7419f9d150b5.tar.xz
some more code from mrieker for system threads, give up of all the other mono dependent theading models only availble for linux (and possible not all platforms). This only has impact on micro-threading switching, and this only happens on long events and only every 60ms, aditionally we do remove a totally extra set of threads (that could grow in a uncontroled way on win) and their hanshake with main ones. This may of course be even more broken now :P
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XMREngine')
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs55
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs1064
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs525
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs118
-rw-r--r--OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs491
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
32using System;
33
34namespace 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
28using log4net; 32using log4net;
29using Mono.Addins; 33using Mono.Addins;
30using Nini.Config; 34using Nini.Config;
@@ -37,11 +41,11 @@ using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.ScriptEngine.Interfaces; 41using OpenSim.Region.ScriptEngine.Interfaces;
38using OpenSim.Region.ScriptEngine.Shared; 42using OpenSim.Region.ScriptEngine.Shared;
39using OpenSim.Region.ScriptEngine.Shared.Api; 43using OpenSim.Region.ScriptEngine.Shared.Api;
40using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
41using OpenMetaverse; 44using OpenMetaverse;
42using System; 45using System;
43using System.Collections; 46using System.Collections;
44using System.Collections.Generic; 47using System.Collections.Generic;
48using System.Diagnostics;
45using System.IO; 49using System.IO;
46using System.Reflection; 50using System.Reflection;
47using System.Reflection.Emit; 51using 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;
31using System.Globalization; 31using System.Globalization;
32using System.IO; 32using System.IO;
33using System.Reflection.Emit; 33using System.Reflection.Emit;
34using System.Runtime.Serialization;
35using System.Text; 34using System.Text;
36using System.Threading; 35using 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
28using Mono.Tasklets;
29using OpenSim.Framework.Monitoring; 28using OpenSim.Framework.Monitoring;
30using System; 29using System;
31using System.Collections.Generic; 30using 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
28using Mono.Tasklets;
29using System; 28using System;
30using System.Collections.Generic;
31using System.Reflection;
32using 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
41namespace OpenSim.Region.ScriptEngine.XMREngine { 35namespace 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
285namespace 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
480namespace 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