aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-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