diff --git a/OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs b/OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs deleted file mode 100644 index 98910aed97..0000000000 --- a/OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// Used to build a dummy Mono.Tasklets.dll file when running on Windows -// Will also work if running with mono, it will just not allow use of -// the "con" and "mmr" thread models, only "sys" will work. - -using System; - -namespace Mono.Tasklets { - public class Continuation : IDisposable - { - public Continuation () - { - throw new NotSupportedException ("'con' thread model requires mono"); - } - public void Dispose () - { } - - public void Mark () - { } - - public int Store (int state) - { - return 0; - } - - public void Restore (int state) - { } - } -} diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs index 6b0410a973..aa8573cbfe 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMREngine.cs @@ -25,6 +25,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// based on XMREngine from Mike Rieker (Dreamnation) and Melanie Thielker +// but with several changes to be more cross platform. + + using log4net; using Mono.Addins; using Nini.Config; @@ -37,11 +41,11 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; using OpenMetaverse; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; @@ -97,7 +101,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private int m_HeapSize; private XMRScriptThread[] m_ScriptThreads; private Thread m_SleepThread = null; -// private Thread m_SliceThread = null; private bool m_Exiting = false; private int m_MaintenanceInterval = 10; @@ -107,15 +110,14 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private object m_FrameUpdateLock = new object (); private event ThreadStart m_FrameUpdateList = null; - /* - * Various instance lists: - * m_InstancesDict = all known instances - * find an instance given its itemID - * m_StartQueue = instances that have just had event queued to them - * m_YieldQueue = instances that are ready to run right now - * m_SleepQueue = instances that have m_SleepUntil valid - * sorted by ascending m_SleepUntil - */ + // Various instance lists: + // m_InstancesDict = all known instances + // find an instance given its itemID + // m_StartQueue = instances that have just had event queued to them + // m_YieldQueue = instances that are ready to run right now + // m_SleepQueue = instances that have m_SleepUntil valid + // sorted by ascending m_SleepUntil + private Dictionary m_InstancesDict = new Dictionary(); public Queue m_ThunkQueue = new Queue (); @@ -126,19 +128,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public XMREngine() { - string envar; - - envar = Environment.GetEnvironmentVariable ("XMREngineTraceCalls"); - m_TraceCalls = (envar != null) && ((envar[0] & 1) != 0); - m_log.Info ("[XMREngine]: m_TraceCalls=" + m_TraceCalls); - - envar = Environment.GetEnvironmentVariable ("XMREngineVerbose"); - m_Verbose = (envar != null) && ((envar[0] & 1) != 0); - m_log.Info ("[XMREngine]: m_Verbose=" + m_Verbose); - - envar = Environment.GetEnvironmentVariable ("XMREngineScriptDebug"); - m_ScriptDebug = (envar != null) && ((envar[0] & 1) != 0); - m_log.Info ("[XMREngine]: m_ScriptDebug=" + m_ScriptDebug); } public string Name @@ -190,97 +179,66 @@ namespace OpenSim.Region.ScriptEngine.XMREngine m_Enabled = false; m_Config = config.Configs["XMREngine"]; - if (m_Config == null) { + if (m_Config == null) + { m_log.Info("[XMREngine]: no config, assuming disabled"); return; } + m_Enabled = m_Config.GetBoolean("Enabled", false); m_log.InfoFormat("[XMREngine]: config enabled={0}", m_Enabled); - if (!m_Enabled) { + if (!m_Enabled) return; - } - - string uThreadModel = "sys"; // will work anywhere - uThreadModel = m_Config.GetString ("UThreadModel", uThreadModel); Type uThreadType = null; - switch (uThreadModel.ToLower ()) { - - // mono continuations - memcpy()s the stack - case "con": { - uThreadType = typeof (ScriptUThread_Con); - break; - } - - // patched mono microthreads - switches stack pointer - case "mmr": { - Exception e = ScriptUThread_MMR.LoadMono (); - if (e != null) { - m_log.Error ("[XMREngine]: mmr thread model not available\n", e); - m_Enabled = false; - return; - } - uThreadType = typeof (ScriptUThread_MMR); - break; - } - - // system threads - works on mono and windows - case "sys": { - uThreadType = typeof (ScriptUThread_Sys); - break; - } - - // who knows what - default: { - m_log.Error ("[XMREngine]: unknown thread model " + uThreadModel); - m_Enabled = false; - return; - } - } - + uThreadType = typeof (ScriptUThread_Nul); uThreadCtor = uThreadType.GetConstructor (new Type[] { typeof (XMRInstance) }); - m_log.Info ("[XMREngine]: using thread model " + uThreadModel); - m_UseSourceHashCode = m_Config.GetBoolean ("UseSourceHashCode", false); - numThreadScriptWorkers = m_Config.GetInt ("NumThreadScriptWorkers", 1); + m_UseSourceHashCode = m_Config.GetBoolean("UseSourceHashCode", false); + numThreadScriptWorkers = m_Config.GetInt("NumThreadScriptWorkers", 3); m_ScriptThreads = new XMRScriptThread[numThreadScriptWorkers]; - for (int i = 0; i < numThreadScriptWorkers; i ++) { - m_ScriptThreads[i] = new XMRScriptThread(this); - } + m_TraceCalls = m_Config.GetBoolean("TraceCalls", false); + m_Verbose = m_Config.GetBoolean("Verbose", false); + m_ScriptDebug = m_Config.GetBoolean("ScriptDebug", false); - m_SleepThread = StartMyThread (RunSleepThread, "xmrengine sleep", ThreadPriority.Normal); -// m_SliceThread = StartMyThread (RunSliceThread, "xmrengine slice", ThreadPriority.Normal); - - /* - * Verify that our ScriptEventCode's match OpenSim's scriptEvent's. - */ + // Verify that our ScriptEventCode's match OpenSim's scriptEvent's. bool err = false; - for (int i = 0; i < 32; i ++) { + for (int i = 0; i < 32; i ++) + { string mycode = "undefined"; string oscode = "undefined"; - try { + try + { mycode = ((ScriptEventCode)i).ToString(); Convert.ToInt32(mycode); mycode = "undefined"; - } catch { } - try { + catch { } + try + { oscode = ((OpenSim.Region.Framework.Scenes.scriptEvents)(1 << i)).ToString(); Convert.ToInt32(oscode); oscode = "undefined"; - } catch { } - if (mycode != oscode) { + catch { } + if (mycode != oscode) + { m_log.ErrorFormat("[XMREngine]: {0} mycode={1}, oscode={2}", i, mycode, oscode); err = true; } } - if (err) { + if (err) + { m_Enabled = false; return; } + for (int i = 0; i < numThreadScriptWorkers; i ++) + m_ScriptThreads[i] = new XMRScriptThread(this, i); + + m_SleepThread = StartMyThread(RunSleepThread, "xmrengine sleep", ThreadPriority.Normal); + m_StackSize = m_Config.GetInt("ScriptStackSize", 2048) << 10; m_HeapSize = m_Config.GetInt("ScriptHeapSize", 1024) << 10; @@ -337,12 +295,11 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private void OneTimeLateInitialization () { - /* - * Build list of defined APIs and their 'this' types and define a field in XMRInstanceSuperType. - */ + // Build list of defined APIs and their 'this' types and define a field in XMRInstanceSuperType. ApiManager am = new ApiManager (); Dictionary apiCtxTypes = new Dictionary (); - foreach (string api in am.GetApis ()) { + foreach (string api in am.GetApis ()) + { m_log.Debug ("[XMREngine]: adding api " + api); IScriptApi scriptApi = am.CreateApi (api); Type apiCtxType = scriptApi.GetType (); @@ -352,25 +309,36 @@ namespace OpenSim.Region.ScriptEngine.XMREngine if (ScriptCodeGen.xmrInstSuperType == null) // Only create type once! { - /* - * Start creating type XMRInstanceSuperType that contains a field - * m_ApiManager_ that points to the per-instance context - * struct for that API, ie, the 'this' value passed to all methods - * in that API. It is in essence: - * - * public class XMRInstanceSuperType : XMRInstance { - * public XMRLSL_Api m_ApiManager_LSL; // 'this' value for all ll...() functions - * public MOD_Api m_ApiManager_MOD; // 'this' value for all mod...() functions - * public OSSL_Api m_ApiManager_OSSL; // 'this' value for all os...() functions - * .... - * } - */ + // Start creating type XMRInstanceSuperType that contains a field + // m_ApiManager_ that points to the per-instance context + // struct for that API, ie, the 'this' value passed to all methods + // in that API. It is in essence: + + // public class XMRInstanceSuperType : XMRInstance { + // public XMRLSL_Api m_ApiManager_LSL; // 'this' value for all ll...() functions + // public MOD_Api m_ApiManager_MOD; // 'this' value for all mod...() functions + // public OSSL_Api m_ApiManager_OSSL; // 'this' value for all os...() functions + // .... + // } + AssemblyName assemblyName = new AssemblyName (); assemblyName.Name = "XMRInstanceSuperAssembly"; - AssemblyBuilder assemblyBuilder = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Run); - ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule ("XMRInstanceSuperModule"); - TypeBuilder typeBuilder = moduleBuilder.DefineType ("XMRInstanceSuperType", TypeAttributes.Public | TypeAttributes.Class); - typeBuilder.SetParent (typeof (XMRInstance)); + AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); +#if DEBUG + Type daType = typeof(DebuggableAttribute); + ConstructorInfo daCtor = daType.GetConstructor(new Type[] { typeof(DebuggableAttribute.DebuggingModes) }); + + CustomAttributeBuilder daBuilder = new CustomAttributeBuilder(daCtor, new object[] { + DebuggableAttribute.DebuggingModes.DisableOptimizations | + DebuggableAttribute.DebuggingModes.EnableEditAndContinue | + DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | + DebuggableAttribute.DebuggingModes.Default }); + + assemblyBuilder.SetCustomAttribute(daBuilder); +#endif + ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("XMRInstanceSuperModule"); + TypeBuilder typeBuilder = moduleBuilder.DefineType("XMRInstanceSuperType", TypeAttributes.Public | TypeAttributes.Class); + typeBuilder.SetParent(typeof (XMRInstance)); foreach (string apiname in apiCtxTypes.Keys) { @@ -378,23 +346,20 @@ namespace OpenSim.Region.ScriptEngine.XMREngine typeBuilder.DefineField (fieldName, apiCtxTypes[apiname], FieldAttributes.Public); } - /* - * Finalize definition of XMRInstanceSuperType. - * Give the compiler a short name to reference it by, - * otherwise it will try to use the AssemblyQualifiedName - * and fail miserably. - */ + // Finalize definition of XMRInstanceSuperType. + // Give the compiler a short name to reference it by, + // otherwise it will try to use the AssemblyQualifiedName + // and fail miserably. ScriptCodeGen.xmrInstSuperType = typeBuilder.CreateType (); ScriptObjWriter.DefineInternalType ("xmrsuper", ScriptCodeGen.xmrInstSuperType); } - /* - * Tell the compiler about all the constants and methods for each API. - * We also tell the compiler how to get the per-instance context for each API - * by reading the corresponding m_ApiManager_ field of XMRInstanceSuperType. - */ - foreach (KeyValuePair kvp in apiCtxTypes) { + // Tell the compiler about all the constants and methods for each API. + // We also tell the compiler how to get the per-instance context for each API + // by reading the corresponding m_ApiManager_ field of XMRInstanceSuperType. + foreach (KeyValuePair kvp in apiCtxTypes) + { // get API name and the corresponding per-instance context type string api = kvp.Key; Type apiCtxType = kvp.Value; @@ -413,41 +378,47 @@ namespace OpenSim.Region.ScriptEngine.XMREngine TokenDeclInline.AddInterfaceMethods (null, apiCtxType.GetMethods (), fieldInfo); } - /* - * Add sim-specific APIs to the compiler. - */ - IScriptModuleComms comms = m_Scene.RequestModuleInterface (); - if (comms != null) { + // Add sim-specific APIs to the compiler. - /* - * Add methods to list of built-in functions. - */ + IScriptModuleComms comms = m_Scene.RequestModuleInterface (); + if (comms != null) + { + // Add methods to list of built-in functions. Delegate[] methods = comms.GetScriptInvocationList (); - foreach (Delegate m in methods) { + foreach (Delegate m in methods) + { MethodInfo mi = m.Method; - try { + try + { CommsCallCodeGen cccg = new CommsCallCodeGen (mi, comms, m_XMRInstanceApiCtxFieldInfos["MOD"]); Verbose ("[XMREngine]: added comms function " + cccg.fullName); - } catch (Exception e) { + } + catch (Exception e) + { m_log.Error ("[XMREngine]: failed to add comms function " + mi.Name); m_log.Error ("[XMREngine]: - " + e.ToString ()); } } - /* - * Add constants to list of built-in constants. - */ + // Add constants to list of built-in constants. + Dictionary consts = comms.GetConstants (); - foreach (KeyValuePair kvp in consts) { - try { + foreach (KeyValuePair kvp in consts) + { + try + { ScriptConst sc = ScriptConst.AddConstant (kvp.Key, kvp.Value); Verbose ("[XMREngine]: added comms constant " + sc.name); - } catch (Exception e) { + } + catch (Exception e) + { m_log.Error ("[XMREngine]: failed to add comms constant " + kvp.Key); m_log.Error ("[XMREngine]: - " + e.Message); } } - } else { + } + else + { Verbose ("[XMREngine]: comms not enabled"); } } @@ -461,7 +432,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine * do some sick type conversions (with corresponding mallocs) so we can't * call the methods directly. */ - private class CommsCallCodeGen : TokenDeclInline { + private class CommsCallCodeGen : TokenDeclInline + { private static Type[] modInvokerArgTypes = new Type[] { typeof (string), typeof (object[]) }; public static FieldInfo xmrInstModApiCtxField; @@ -492,8 +464,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { methName = mi.Name; string modInvokerName = comms.LookupModInvocation (methName); - if (modInvokerName == null) throw new Exception ("cannot find comms method " + methName); - modInvokerMeth = typeof (MOD_Api).GetMethod (modInvokerName, modInvokerArgTypes); + if (modInvokerName == null) + throw new Exception("cannot find comms method " + methName); + modInvokerMeth = typeof(MOD_Api).GetMethod(modInvokerName, modInvokerArgTypes); xmrInstModApiCtxField = apictxfi; } @@ -504,7 +477,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine sb.Append (mi.Name); sb.Append ('('); ParameterInfo[] mps = mi.GetParameters (); - for (int i = 2; i < mps.Length; i ++) { + for (int i = 2; i < mps.Length; i ++) + { ParameterInfo pi = mps[i]; if (i > 2) sb.Append (','); sb.Append (ParamType (pi.ParameterType)); @@ -551,36 +525,31 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args) { - /* - * Set up 'this' pointer for modInvoker?() = value from ApiManager.CreateApi("MOD"). - */ + // Set up 'this' pointer for modInvoker?() = value from ApiManager.CreateApi("MOD"). scg.PushXMRInst (); scg.ilGen.Emit (errorAt, OpCodes.Castclass, xmrInstModApiCtxField.DeclaringType); scg.ilGen.Emit (errorAt, OpCodes.Ldfld, xmrInstModApiCtxField); - /* - * Set up 'fname' argument to modInvoker?() = name of the function to be called. - */ + // Set up 'fname' argument to modInvoker?() = name of the function to be called. scg.ilGen.Emit (errorAt, OpCodes.Ldstr, methName); - /* - * Set up 'parms' argument to modInvoker?() = object[] of the script-visible parameters, - * in their LSL-wrapped form. Of course, the modInvoker?() method will malloc yet another - * object[] and type-convert these parameters one-by-one with another round of unwrapping - * and wrapping. - * Types allowed in this object[]: - * LSL_Float, LSL_Integer, LSL_Key, LSL_List, LSL_Rotation, LSL_String, LSL_Vector - */ + // Set up 'parms' argument to modInvoker?() = object[] of the script-visible parameters, + // in their LSL-wrapped form. Of course, the modInvoker?() method will malloc yet another + // object[] and type-convert these parameters one-by-one with another round of unwrapping + // and wrapping. + // Types allowed in this object[]: + // LSL_Float, LSL_Integer, LSL_Key, LSL_List, LSL_Rotation, LSL_String, LSL_Vector + int nargs = args.Length; scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4, nargs); scg.ilGen.Emit (errorAt, OpCodes.Newarr, typeof (object)); - for (int i = 0; i < nargs; i ++) { + for (int i = 0; i < nargs; i ++) + { scg.ilGen.Emit (errorAt, OpCodes.Dup); scg.ilGen.Emit (errorAt, OpCodes.Ldc_I4, i); // get location and type of argument - CompValu arg = args[i]; TokenType argtype = arg.type; @@ -593,68 +562,84 @@ namespace OpenSim.Region.ScriptEngine.XMREngine // then convert to object by boxing if necessary Type boxit = null; - if (argtype is TokenTypeLSLFloat) { + if (argtype is TokenTypeLSLFloat) + { args[i].PushVal (scg, errorAt); boxit = typeof (LSL_Float); - } else if (argtype is TokenTypeLSLInt) { + } + else if (argtype is TokenTypeLSLInt) + { args[i].PushVal (scg, errorAt); boxit = typeof (LSL_Integer); - } else if (argtype is TokenTypeLSLKey) { + } + else if (argtype is TokenTypeLSLKey) + { args[i].PushVal (scg, errorAt); boxit = typeof (LSL_Key); - } else if (argtype is TokenTypeList) { + } + else if (argtype is TokenTypeList) + { args[i].PushVal (scg, errorAt); boxit = typeof (LSL_List); - } else if (argtype is TokenTypeRot) { + } + else if (argtype is TokenTypeRot) + { args[i].PushVal (scg, errorAt); boxit = typeof (LSL_Rotation); - } else if (argtype is TokenTypeLSLString) { + } + else if (argtype is TokenTypeLSLString) + { args[i].PushVal (scg, errorAt); boxit = typeof (LSL_String); - } else if (argtype is TokenTypeVec) { + } + else if (argtype is TokenTypeVec) + { args[i].PushVal (scg, errorAt); boxit = typeof (LSL_Vector); - } else if (argtype is TokenTypeFloat) { + } + else if (argtype is TokenTypeFloat) + { args[i].PushVal (scg, errorAt, new TokenTypeLSLFloat (argtype)); boxit = typeof (LSL_Float); - } else if (argtype is TokenTypeInt) { + } + else if (argtype is TokenTypeInt) + { args[i].PushVal (scg, errorAt, new TokenTypeLSLInt (argtype)); boxit = typeof (LSL_Integer); - } else if (argtype is TokenTypeKey) { + } + else if (argtype is TokenTypeKey) + { args[i].PushVal (scg, errorAt, new TokenTypeLSLKey (argtype)); boxit = typeof (LSL_Key); - } else if (argtype is TokenTypeStr) { + } + else if (argtype is TokenTypeStr) + { args[i].PushVal (scg, errorAt, new TokenTypeLSLString (argtype)); boxit = typeof (LSL_String); - } else { + } + else throw new Exception ("unsupported arg type " + argtype.GetType ().Name); - } - if (boxit.IsValueType) { + + if (boxit.IsValueType) scg.ilGen.Emit (errorAt, OpCodes.Box, boxit); - } // pop the object into the object[] - scg.ilGen.Emit (errorAt, OpCodes.Stelem, typeof (object)); } - /* - * Call the modInvoker?() method. - * It leaves an LSL-wrapped type on the stack. - */ - if (modInvokerMeth.IsVirtual) { + // Call the modInvoker?() method. + // It leaves an LSL-wrapped type on the stack. + if (modInvokerMeth.IsVirtual) scg.ilGen.Emit (errorAt, OpCodes.Callvirt, modInvokerMeth); - } else { + else scg.ilGen.Emit (errorAt, OpCodes.Call, modInvokerMeth); - } - /* - * The 3rd arg to Pop() is the type on the stack, - * ie, what modInvoker?() actually returns. - * The Pop() method will wrap/unwrap as needed. - */ + // The 3rd arg to Pop() is the type on the stack, + // ie, what modInvoker?() actually returns. + // The Pop() method will wrap/unwrap as needed. Type retSysType = modInvokerMeth.ReturnType; - if (retSysType == null) retSysType = typeof (void); + if (retSysType == null) + retSysType = typeof (void); TokenType retTokType = TokenType.FromSysType (errorAt, retSysType); result.Pop (scg, errorAt, retTokType); } @@ -671,17 +656,23 @@ namespace OpenSim.Region.ScriptEngine.XMREngine TraceCalls("[XMREngine]: XMREngine.RemoveRegion({0})", scene.RegionInfo.RegionName); - /* - * Write script states out to .state files so it will be - * available when the region is restarted. - */ + // Write script states out to .state files so it will be + // available when the region is restarted. DoMaintenance(null, null); - /* - * Stop executing script threads and wait for final - * one to finish (ie, script gets to CheckRun() call). - */ + // Stop executing script threads and wait for final + // one to finish (ie, script gets to CheckRun() call). m_Exiting = true; + + m_Scene.EventManager.OnFrame -= OnFrame; + m_Scene.EventManager.OnRezScript -= OnRezScript; + m_Scene.EventManager.OnRemoveScript -= OnRemoveScript; + m_Scene.EventManager.OnScriptReset -= OnScriptReset; + m_Scene.EventManager.OnStartScript -= OnStartScript; + m_Scene.EventManager.OnStopScript -= OnStopScript; + m_Scene.EventManager.OnGetScriptRunning -= OnGetScriptRunning; + m_Scene.EventManager.OnShutdown -= OnShutdown; + for (int i = 0; i < numThreadScriptWorkers; i ++) { XMRScriptThread scriptThread = m_ScriptThreads[i]; @@ -702,21 +693,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine m_SleepThread.Abort(); m_SleepThread = null; } -/* - if (m_SliceThread != null) - { - m_SliceThread.Join(); - m_SliceThread = null; - } -*/ - m_Scene.EventManager.OnFrame -= OnFrame; - m_Scene.EventManager.OnRezScript -= OnRezScript; - m_Scene.EventManager.OnRemoveScript -= OnRemoveScript; - m_Scene.EventManager.OnScriptReset -= OnScriptReset; - m_Scene.EventManager.OnStartScript -= OnStartScript; - m_Scene.EventManager.OnStopScript -= OnStopScript; - m_Scene.EventManager.OnGetScriptRunning -= OnGetScriptRunning; - m_Scene.EventManager.OnShutdown -= OnShutdown; m_Enabled = false; m_Scene = null; @@ -758,46 +734,51 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private void RunTest (string module, string[] args) { - if (args.Length < 2) { + if (args.Length < 2) + { m_log.Info ("[XMREngine]: missing command, try 'xmr help'"); return; } - switch (args[1]) { - case "cvv": { - switch (args.Length) { - case 2: { + switch (args[1]) + { + case "cvv": + switch (args.Length) + { + case 2: m_log.InfoFormat ("[XMREngine]: compiled version value = {0}", ScriptCodeGen.COMPILED_VERSION_VALUE); break; - } - case 3: { - try { + + case 3: + try + { ScriptCodeGen.COMPILED_VERSION_VALUE = Convert.ToInt32 (args[2]); - } catch { + } + catch + { m_log.Error ("[XMREngine]: bad/missing version number"); } break; - } - default: { + + default: m_log.Error ("[XMREngine]: xmr cvv []"); break; - } } break; - } - case "echo": { - for (int i = 0; i < args.Length; i ++) { + + case "echo": + for (int i = 0; i < args.Length; i ++) m_log.Info ("[XMREngine]: echo[" + i + "]=<" + args[i] + ">"); - } + break; - } - case "gc": { + + case "gc": GC.Collect(); break; - } + case "help": - case "?": { + case "?": m_log.Info ("[XMREngine]: xmr cvv [] - show/set compiled version value"); m_log.Info ("[XMREngine]: xmr gc"); m_log.Info ("[XMREngine]: xmr ls [-help ...]"); @@ -809,75 +790,74 @@ namespace OpenSim.Region.ScriptEngine.XMREngine m_log.Info ("[XMREngine]: xmr tracecalls [yes | no]"); m_log.Info ("[XMREngine]: xmr verbose [yes | no]"); break; - } - case "ls": { + + case "ls": XmrTestLs (args, 2); break; - } - case "mvv": { - switch (args.Length) { - case 2: { + + case "mvv": + switch (args.Length) + { + case 2: m_log.InfoFormat ("[XMREngine]: migration version value = {0}", XMRInstance.migrationVersion); break; - } - case 3: { - try { + + case 3: + try + { int mvv = Convert.ToInt32 (args[2]); if ((mvv < 0) || (mvv > 255)) throw new Exception ("out of range"); XMRInstance.migrationVersion = (byte) mvv; - } catch (Exception e) { + } + catch (Exception e) + { m_log.Error ("[XMREngine]: bad/missing version number (" + e.Message + ")"); } break; - } - default: { + + default: m_log.Error ("[XMREngine]: xmr mvv []"); break; - } } break; - } - case "pev": { + + case "pev": XmrTestPev (args, 2); break; - } - case "reset": { + + case "reset": XmrTestReset (args, 2); break; - } - case "resume": { + + case "resume": m_log.Info ("[XMREngine]: resuming scripts"); - for (int i = 0; i < numThreadScriptWorkers; i ++) { + for (int i = 0; i < numThreadScriptWorkers; i ++) m_ScriptThreads[i].ResumeThread(); - } + break; - } - case "suspend": { + + case "suspend": m_log.Info ("[XMREngine]: suspending scripts"); - for (int i = 0; i < numThreadScriptWorkers; i ++) { + for (int i = 0; i < numThreadScriptWorkers; i ++) m_ScriptThreads[i].SuspendThread(); - } break; - } - case "tracecalls": { - if (args.Length > 2) { + + case "tracecalls": + if (args.Length > 2) m_TraceCalls = (args[2][0] & 1) != 0; - } m_log.Info ("[XMREngine]: tracecalls " + (m_TraceCalls ? "yes" : "no")); break; - } - case "verbose": { - if (args.Length > 2) { + + case "verbose": + if (args.Length > 2) m_Verbose = (args[2][0] & 1) != 0; - } m_log.Info ("[XMREngine]: verbose " + (m_Verbose ? "yes" : "no")); break; - } - default: { + + default: m_log.Error ("[XMREngine]: unknown command " + args[1] + ", try 'xmr help'"); break; - } } } @@ -935,23 +915,21 @@ namespace OpenSim.Region.ScriptEngine.XMREngine TraceCalls("[XMREngine]: XMREngine.PostObjectEvent({0},{1})", localID.ToString(), parms.EventName); - /* - * In SecondLife, attach events go to all scripts of all prims - * in a linked object. So here we duplicate that functionality, - * as all we ever get is a single attach event for the whole - * object. - */ - if (parms.EventName == "attach") { + // In SecondLife, attach events go to all scripts of all prims + // in a linked object. So here we duplicate that functionality, + // as all we ever get is a single attach event for the whole + // object. + if (parms.EventName == "attach") + { bool posted = false; - foreach (SceneObjectPart primpart in part.ParentGroup.Parts) { + foreach (SceneObjectPart primpart in part.ParentGroup.Parts) + { posted |= PostPrimEvent (primpart, parms); } return posted; } - /* - * Other events go to just the scripts in that prim. - */ + // Other events go to just the scripts in that prim. return PostPrimEvent (part, parms); } @@ -959,34 +937,33 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { UUID partUUID = part.UUID; - /* - * Get list of script instances running in the object. - */ + // Get list of script instances running in the object. XMRInstance[] objInstArray; - lock (m_InstancesDict) { - if (!m_ObjectInstArray.TryGetValue (partUUID, out objInstArray)) { + lock (m_InstancesDict) + { + if (!m_ObjectInstArray.TryGetValue (partUUID, out objInstArray)) return false; - } - if (objInstArray == null) { + + if (objInstArray == null) + { objInstArray = RebuildObjectInstArray (partUUID); m_ObjectInstArray[partUUID] = objInstArray; } } - /* - * Post event to all script instances in the object. - */ + // Post event to all script instances in the object. if (objInstArray.Length <= 0) return false; - foreach (XMRInstance inst in objInstArray) { + foreach (XMRInstance inst in objInstArray) inst.PostEvent (parms); - } + return true; } public DetectParams GetDetectParams(UUID itemID, int number) { XMRInstance instance = GetInstance (itemID); - if (instance == null) return null; + if (instance == null) + return null; return instance.GetDetectParams(number); } @@ -997,7 +974,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public int GetStartParameter(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance == null) return 0; + if (instance == null) + return 0; return instance.StartParam; } @@ -1010,9 +988,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public void SetScriptState(UUID itemID, bool state) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) instance.Running = state; - } } // Control display of the "running" checkbox @@ -1020,7 +997,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public bool GetScriptState(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance == null) return false; + if (instance == null) + return false; return instance.Running; } @@ -1032,15 +1010,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public void ApiResetScript(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) instance.ApiReset(); - } } public void ResetScript(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) + { IUrlModule urlModule = m_Scene.RequestModuleInterface(); if (urlModule != null) urlModule.ScriptRemoved(itemID); @@ -1067,7 +1045,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public IScriptApi GetApi(UUID itemID, string name) { FieldInfo fi; - if (!m_XMRInstanceApiCtxFieldInfos.TryGetValue (name, out fi)) return null; + if (!m_XMRInstanceApiCtxFieldInfos.TryGetValue (name, out fi)) + return null; XMRInstance inst = GetInstance (itemID); if (inst == null) return null; return (IScriptApi)fi.GetValue (inst); @@ -1081,11 +1060,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public string GetXMLState(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance == null) return String.Empty; + if (instance == null) + return String.Empty; TraceCalls("[XMREngine]: XMREngine.GetXMLState({0})", itemID.ToString()); - if (!instance.m_HasRun) return String.Empty; + if (!instance.m_HasRun) + return String.Empty; XmlDocument doc = new XmlDocument(); @@ -1108,10 +1089,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine assetA.Value = assetID; stateN.Attributes.Append(assetA); - /* - * Get ... item that hold's script's state. - * This suspends the script if necessary then takes a snapshot. - */ + // Get ... item that hold's script's state. + // This suspends the script if necessary then takes a snapshot. XmlElement scriptStateN = instance.GetExecutionState(doc); stateN.AppendChild(scriptStateN); @@ -1147,13 +1126,12 @@ namespace OpenSim.Region.ScriptEngine.XMREngine // ... contains contents of .state file. XmlElement scriptStateN = (XmlElement)stateN.SelectSingleNode("ScriptState"); - if (scriptStateN == null) { + if (scriptStateN == null) return false; - } + string sen = stateN.GetAttribute("Engine"); - if ((sen == null) || (sen != ScriptEngineName)) { + if ((sen == null) || (sen != ScriptEngineName)) return false; - } XmlAttribute assetA = doc.CreateAttribute("", "Asset", ""); assetA.Value = stateN.GetAttribute("Asset"); @@ -1198,9 +1176,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public void SleepScript(UUID itemID, int delay) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) instance.Sleep (delay); - } } // Get a script instance loaded, compiling it if necessary @@ -1219,21 +1196,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID); - if (!m_LateInit) { + if (!m_LateInit) + { m_LateInit = true; OneTimeLateInitialization (); } TraceCalls("[XMREngine]: OnRezScript(...,{0},...)", itemID.ToString()); - /* - * Assume script uses the default engine, whatever that is. - */ + // Assume script uses the default engine, whatever that is. string engineName = defEngine; - /* - * Very first line might contain "//" scriptengine ":". - */ + // Very first line might contain "//" scriptengine ":". string firstline = ""; if (script.StartsWith("//")) { int lineEnd = script.IndexOf('\n'); @@ -1245,39 +1219,32 @@ namespace OpenSim.Region.ScriptEngine.XMREngine } } - /* - * Make sure the default or requested engine is us. - */ + // Make sure the default or requested engine is us. if (engineName != ScriptEngineName) { - /* - * Not us, if requested engine exists, silently ignore script and let - * requested engine handle it. - */ + // Not us, if requested engine exists, silently ignore script and let + // requested engine handle it. IScriptModule[] engines = m_Scene.RequestModuleInterfaces (); - foreach (IScriptModule eng in engines) { - if (eng.ScriptEngineName == engineName) { + foreach (IScriptModule eng in engines) + { + if (eng.ScriptEngineName == engineName) return; - } } - /* - * Requested engine not defined, warn on console. - * Then we try to handle it if we're the default engine, else we ignore it. - */ + // Requested engine not defined, warn on console. + // Then we try to handle it if we're the default engine, else we ignore it. m_log.Warn ("[XMREngine]: " + itemID.ToString() + " requests undefined/disabled engine " + engineName); m_log.Info ("[XMREngine]: - " + part.GetWorldPosition ()); m_log.Info ("[XMREngine]: first line: " + firstline); - if (defEngine != ScriptEngineName) { + if (defEngine != ScriptEngineName) + { m_log.Info ("[XMREngine]: leaving it to the default script engine (" + defEngine + ") to process it"); return; } m_log.Info ("[XMREngine]: will attempt to processing it anyway as default script engine"); } - /* - * Put on object/instance lists. - */ + // Put on object/instance lists. XMRInstance instance = (XMRInstance)Activator.CreateInstance (ScriptCodeGen.xmrInstSuperType); instance.m_LocalID = localID; instance.m_ItemID = itemID; @@ -1291,7 +1258,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine instance.m_DescName = part.Name + ":" + item.Name; instance.m_IState = XMRInstState.CONSTRUCT; - lock (m_InstancesDict) { + lock (m_InstancesDict) + { m_LockedDict = "RegisterInstance"; // Insert on internal list of all scripts being handled by this engine instance. @@ -1300,11 +1268,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine // Insert on internal list of all scripts being handled by this engine instance // that are part of the object. List itemIDList; - if (!m_ObjectItemList.TryGetValue(instance.m_PartUUID, out itemIDList)) { + if (!m_ObjectItemList.TryGetValue(instance.m_PartUUID, out itemIDList)) + { itemIDList = new List(); m_ObjectItemList[instance.m_PartUUID] = itemIDList; } - if (!itemIDList.Contains(instance.m_ItemID)) { + if (!itemIDList.Contains(instance.m_ItemID)) + { itemIDList.Add(instance.m_ItemID); m_ObjectInstArray[instance.m_PartUUID] = null; } @@ -1312,12 +1282,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine m_LockedDict = "~RegisterInstance"; } - /* - * Compile and load it. - */ - lock (m_ScriptErrors) { + // Compile and load it. + lock (m_ScriptErrors) m_ScriptErrors.Remove (instance.m_ItemID); - } + LoadThreadWork (instance); } @@ -1326,17 +1294,20 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ private void LoadThreadWork (XMRInstance instance) { - /* - * Compile and load the script in memory. - */ + // Compile and load the script in memory. + ArrayList errors = new ArrayList(); Exception initerr = null; - try { + try + { instance.Initialize(this, m_ScriptBasePath, m_StackSize, m_HeapSize, errors); - } catch (Exception e1) { + } + catch (Exception e1) + { initerr = e1; } - if ((initerr != null) && !instance.m_ForceRecomp) { + if ((initerr != null) && !instance.m_ForceRecomp) + { UUID itemID = instance.m_ItemID; Verbose ("[XMREngine]: {0}/{2} first load failed ({1}), retrying after recompile", itemID.ToString(), initerr.Message, instance.m_Item.AssetID.ToString()); @@ -1344,62 +1315,66 @@ namespace OpenSim.Region.ScriptEngine.XMREngine initerr = null; errors = new ArrayList(); instance.m_ForceRecomp = true; - try { + try + { instance.Initialize(this, m_ScriptBasePath, m_StackSize, m_HeapSize, errors); - } catch (Exception e2) { + } + catch (Exception e2) + { initerr = e2; } } - if (initerr != null) { + if (initerr != null) + { UUID itemID = instance.m_ItemID; Verbose ("[XMREngine]: Error starting script {0}/{2}: {1}", itemID.ToString(), initerr.Message, instance.m_Item.AssetID.ToString()); - if (initerr.Message != "compilation errors") { + if (initerr.Message != "compilation errors") + { Verbose ("[XMREngine]: - " + instance.m_Part.GetWorldPosition () + " " + instance.m_DescName); Verbose ("[XMREngine]: exception:\n{0}", initerr.ToString()); } OnRemoveScript (0, itemID); - /* - * Post errors where GetScriptErrors() can see them. - */ - if (errors.Count == 0) { + // Post errors where GetScriptErrors() can see them. + + if (errors.Count == 0) errors.Add(initerr.Message); - } else { - foreach (Object err in errors) { + else + { + foreach (Object err in errors) + { if (m_ScriptDebug) m_log.DebugFormat ("[XMREngine]: {0}", err.ToString()); } } - lock (m_ScriptErrors) { + + lock (m_ScriptErrors) m_ScriptErrors[instance.m_ItemID] = errors; - } return; } - /* - * Tell GetScriptErrors() that we have finished compiling/loading - * successfully (by posting a 0 element array). - */ - lock (m_ScriptErrors) { + // Tell GetScriptErrors() that we have finished compiling/loading + // successfully (by posting a 0 element array). + lock (m_ScriptErrors) + { if (instance.m_IState != XMRInstState.CONSTRUCT) throw new Exception("bad state"); m_ScriptErrors[instance.m_ItemID] = noScriptErrors; } - /* - * Transition from CONSTRUCT->ONSTARTQ and give to RunScriptThread(). - * Put it on the start queue so it will run any queued event handlers, - * such as state_entry() or on_rez(). If there aren't any queued, it - * will just go to idle state when RunOne() tries to dequeue an event. - */ - lock (instance.m_QueueLock) { - if (instance.m_IState != XMRInstState.CONSTRUCT) throw new Exception("bad state"); + // Transition from CONSTRUCT->ONSTARTQ and give to RunScriptThread(). + // Put it on the start queue so it will run any queued event handlers, + // such as state_entry() or on_rez(). If there aren't any queued, it + // will just go to idle state when RunOne() tries to dequeue an event. + lock (instance.m_QueueLock) + { + if (instance.m_IState != XMRInstState.CONSTRUCT) + throw new Exception("bad state"); instance.m_IState = XMRInstState.ONSTARTQ; - if (!instance.m_Running) { + if (!instance.m_Running) instance.EmptyEventQueues (); - } } QueueToStart(instance); } @@ -1408,66 +1383,57 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { TraceCalls("[XMREngine]: OnRemoveScript(...,{0})", itemID.ToString()); - /* - * Remove from our list of known scripts. - * After this, no more events can queue because we won't be - * able to translate the itemID to an XMRInstance pointer. - */ + // Remove from our list of known scripts. + // After this, no more events can queue because we won't be + // able to translate the itemID to an XMRInstance pointer. + XMRInstance instance = null; lock (m_InstancesDict) { m_LockedDict = "OnRemoveScript:" + itemID.ToString(); - /* - * Tell the instance to free off everything it can. - */ + // Tell the instance to free off everything it can. + if (!m_InstancesDict.TryGetValue(itemID, out instance)) { m_LockedDict = "~OnRemoveScript"; return; } - /* - * Tell it to stop executing anything. - */ + // Tell it to stop executing anything. instance.suspendOnCheckRunHold = true; - /* - * Remove it from our list of known script instances - * mostly so no more events can queue to it. - */ + // Remove it from our list of known script instances + // mostly so no more events can queue to it. m_InstancesDict.Remove(itemID); List itemIDList; - if (m_ObjectItemList.TryGetValue (instance.m_PartUUID, out itemIDList)) { + if (m_ObjectItemList.TryGetValue (instance.m_PartUUID, out itemIDList)) + { itemIDList.Remove(itemID); - if (itemIDList.Count == 0) { + if (itemIDList.Count == 0) + { m_ObjectItemList.Remove(instance.m_PartUUID); m_ObjectInstArray.Remove(instance.m_PartUUID); - } else { - m_ObjectInstArray[instance.m_PartUUID] = null; } + else + m_ObjectInstArray[instance.m_PartUUID] = null; } - /* - * Delete the .state file as any needed contents were fetched with GetXMLState() - * and stored on the database server. - */ + // Delete the .state file as any needed contents were fetched with GetXMLState() + // and stored on the database server. string stateFileName = XMRInstance.GetStateFileName(m_ScriptBasePath, itemID); File.Delete(stateFileName); ScriptRemoved handlerScriptRemoved = OnScriptRemoved; - if (handlerScriptRemoved != null) { + if (handlerScriptRemoved != null) handlerScriptRemoved(itemID); - } m_LockedDict = "~~OnRemoveScript"; } - /* - * Free off its stack and fun things like that. - * If it is running, abort it. - */ + // Free off its stack and fun things like that. + // If it is running, abort it. instance.Dispose (); } @@ -1480,31 +1446,33 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public void OnStartScript(uint localID, UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) instance.Running = true; - } } public void OnStopScript(uint localID, UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) instance.Running = false; - } } public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) + { TraceCalls("[XMREngine]: XMREngine.OnGetScriptRunning({0},{1})", objectID.ToString(), itemID.ToString()); IEventQueue eq = World.RequestModuleInterface(); - if (eq == null) { + if (eq == null) + { controllingClient.SendScriptRunningReply(objectID, itemID, instance.Running); - } else { + } + else + { eq.Enqueue(EventQueueHelper.ScriptRunningReplyEvent(objectID, itemID, instance.Running, true), controllingClient.AgentId); @@ -1515,7 +1483,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public bool HasScript(UUID itemID, out bool running) { XMRInstance instance = GetInstance (itemID); - if (instance == null) { + if (instance == null) + { running = true; return false; } @@ -1529,9 +1498,11 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ private void OnFrame () { - if (m_FrameUpdateList != null) { + if (m_FrameUpdateList != null) + { ThreadStart frameupdates; - lock (m_FrameUpdateLock) { + lock (m_FrameUpdateLock) + { frameupdates = m_FrameUpdateList; m_FrameUpdateList = null; } @@ -1545,9 +1516,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ public void AddOnFrameUpdate (ThreadStart thunk) { - lock (m_FrameUpdateLock) { + lock (m_FrameUpdateLock) m_FrameUpdateList += thunk; - } } /** @@ -1570,7 +1540,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ public void QueueToStart(XMRInstance inst) { - lock (m_StartQueue) { + lock (m_StartQueue) + { if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); m_StartQueue.InsertTail(inst); } @@ -1582,28 +1553,25 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ public void WakeFromSleep(XMRInstance inst) { - /* - * Remove from sleep queue unless someone else already woke it. - */ - lock (m_SleepQueue) { - if (inst.m_IState != XMRInstState.ONSLEEPQ) { + // Remove from sleep queue unless someone else already woke it. + lock (m_SleepQueue) + { + if (inst.m_IState != XMRInstState.ONSLEEPQ) return; - } + m_SleepQueue.Remove(inst); inst.m_IState = XMRInstState.REMDFROMSLPQ; } - /* - * Put on end of list of scripts that are ready to run. - */ - lock (m_YieldQueue) { + // Put on end of list of scripts that are ready to run. + lock (m_YieldQueue) + { inst.m_IState = XMRInstState.ONYIELDQ; m_YieldQueue.InsertTail(inst); } - /* - * Make sure the OS thread is running so it will see the script. - */ + + // Make sure the OS thread is running so it will see the script. XMRScriptThread.WakeUpOne(); } @@ -1616,96 +1584,89 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ public void HandleNewIState(XMRInstance inst, XMRInstState newIState) { - /* - * RunOne() should have left the instance in RUNNING state. - */ - if (inst.m_IState != XMRInstState.RUNNING) throw new Exception("bad state"); - /* - * Now see what RunOne() wants us to do with the instance next. - */ - switch (newIState) { + // RunOne() should have left the instance in RUNNING state. + if (inst.m_IState != XMRInstState.RUNNING) + throw new Exception("bad state"); - /* - * Instance has set m_SleepUntil to when it wants to sleep until. - * So insert instance in sleep queue by ascending wake time. - * Then wake the timer thread if this is the new first entry - * so it will reset its timer. - */ - case XMRInstState.ONSLEEPQ: { - lock (m_SleepQueue) { + + // Now see what RunOne() wants us to do with the instance next. + switch (newIState) + { + + // Instance has set m_SleepUntil to when it wants to sleep until. + // So insert instance in sleep queue by ascending wake time. + // Then wake the timer thread if this is the new first entry + // so it will reset its timer. + case XMRInstState.ONSLEEPQ: + lock (m_SleepQueue) + { XMRInstance after; inst.m_IState = XMRInstState.ONSLEEPQ; - for (after = m_SleepQueue.PeekHead(); after != null; after = after.m_NextInst) { - if (after.m_SleepUntil > inst.m_SleepUntil) break; + for (after = m_SleepQueue.PeekHead(); after != null; after = after.m_NextInst) + { + if (after.m_SleepUntil > inst.m_SleepUntil) + break; } m_SleepQueue.InsertBefore(inst, after); - if (m_SleepQueue.PeekHead() == inst) { + if (m_SleepQueue.PeekHead() == inst) + { Monitor.Pulse (m_SleepQueue); } } break; - } - /* - * Instance just took a long time to run and got wacked by the - * slicer. So put on end of yield queue to let someone else - * run. If there is no one else, it will run again right away. - */ - case XMRInstState.ONYIELDQ: { - lock (m_YieldQueue) { + // Instance just took a long time to run and got wacked by the + // slicer. So put on end of yield queue to let someone else + // run. If there is no one else, it will run again right away. + case XMRInstState.ONYIELDQ: + lock (m_YieldQueue) + { inst.m_IState = XMRInstState.ONYIELDQ; m_YieldQueue.InsertTail(inst); } break; - } - /* - * Instance finished executing an event handler. So if there is - * another event queued for it, put it on the start queue so it - * will process the new event. Otherwise, mark it idle and the - * next event to queue to it will start it up. - */ - case XMRInstState.FINISHED: { + // Instance finished executing an event handler. So if there is + // another event queued for it, put it on the start queue so it + // will process the new event. Otherwise, mark it idle and the + // next event to queue to it will start it up. + case XMRInstState.FINISHED: Monitor.Enter(inst.m_QueueLock); - if (!inst.m_Suspended && (inst.m_EventQueue.Count > 0)) { + if (!inst.m_Suspended && (inst.m_EventQueue.Count > 0)) + { Monitor.Exit(inst.m_QueueLock); - lock (m_StartQueue) { + lock (m_StartQueue) + { inst.m_IState = XMRInstState.ONSTARTQ; m_StartQueue.InsertTail (inst); } - } else { + } + else + { inst.m_IState = XMRInstState.IDLE; Monitor.Exit(inst.m_QueueLock); } break; - } - /* - * Its m_SuspendCount > 0. - * Don't put it on any queue and it won't run. - * Since it's not IDLE, even queuing an event won't start it. - */ - case XMRInstState.SUSPENDED: { + // Its m_SuspendCount > 0. + // Don't put it on any queue and it won't run. + // Since it's not IDLE, even queuing an event won't start it. + case XMRInstState.SUSPENDED: inst.m_IState = XMRInstState.SUSPENDED; break; - } - /* - * It has been disposed of. - * Just set the new state and all refs should theoretically drop off - * as the instance is no longer in any list. - */ - case XMRInstState.DISPOSED: { + // It has been disposed of. + // Just set the new state and all refs should theoretically drop off + // as the instance is no longer in any list. + case XMRInstState.DISPOSED: inst.m_IState = XMRInstState.DISPOSED; break; - } - /* - * RunOne returned something bad. - */ - default: throw new Exception("bad new state"); + // RunOne returned something bad. + default: + throw new Exception("bad new state"); } } @@ -1718,45 +1679,48 @@ namespace OpenSim.Region.ScriptEngine.XMREngine int deltaMS; XMRInstance inst; - while (true) { - lock (m_SleepQueue) { + while (true) + { + lock (m_SleepQueue) + { - /* - * Wait here until there is a script on the timer queue that has expired. - */ - while (true) { + // Wait here until there is a script on the timer queue that has expired. + while (true) + { UpdateMyThread (); - if (m_Exiting) { + if (m_Exiting) + { MyThreadExiting (); return; } inst = m_SleepQueue.PeekHead(); - if (inst == null) { + if (inst == null) + { Monitor.Wait (m_SleepQueue, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); continue; } if (inst.m_IState != XMRInstState.ONSLEEPQ) throw new Exception("bad state"); deltaTS = (inst.m_SleepUntil - DateTime.UtcNow).TotalMilliseconds; - if (deltaTS <= 0.0) break; + if (deltaTS <= 0.0) + break; deltaMS = Int32.MaxValue; - if (deltaTS < Int32.MaxValue) deltaMS = (int)deltaTS; - if (deltaMS > Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2) { + if (deltaTS < Int32.MaxValue) + deltaMS = (int)deltaTS; + if (deltaMS > Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2) + { deltaMS = Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2; } Monitor.Wait (m_SleepQueue, deltaMS); } - /* - * Remove the expired entry from the timer queue. - */ + // Remove the expired entry from the timer queue. m_SleepQueue.RemoveHead(); inst.m_IState = XMRInstState.REMDFROMSLPQ; } - /* - * Post the script to the yield queue so it will run and wake a script thread to run it. - */ - lock (m_YieldQueue) { + // Post the script to the yield queue so it will run and wake a script thread to run it. + lock (m_YieldQueue) + { inst.m_IState = XMRInstState.ONYIELDQ; m_YieldQueue.InsertTail(inst); } @@ -1767,42 +1731,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine /** * @brief Thread that runs a time slicer. */ -/* - private void RunSliceThread() - { - int ms = m_Config.GetInt ("TimeSlice", 50); - while (!m_Exiting) { - UpdateMyThread (); -*/ - /* - * Let script run for a little bit. - */ -// System.Threading.Thread.Sleep (ms); - - /* - * If some script is running, flag it to suspend - * next time it calls CheckRun(). - */ -/* for (int i = 0; i < numThreadScriptWorkers; i ++) { - XMRScriptThread st = m_ScriptThreads[i]; - if (st != null) st.TimeSlice(); - } - } - MyThreadExiting (); - } -*/ public void Suspend(UUID itemID, int ms) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) instance.Sleep(ms); - } } public void Die(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) + { TraceCalls("[XMREngine]: XMREngine.Die({0})", itemID.ToString()); instance.Die(); } @@ -1819,10 +1759,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public XMRInstance GetInstance(UUID itemID) { XMRInstance instance; - lock (m_InstancesDict) { - if (!m_InstancesDict.TryGetValue(itemID, out instance)) { + lock (m_InstancesDict) + { + if (!m_InstancesDict.TryGetValue(itemID, out instance)) instance = null; - } } return instance; } @@ -1834,9 +1774,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { XMRInstance[] instanceArray; - lock (m_InstancesDict) { + lock (m_InstancesDict) instanceArray = System.Linq.Enumerable.ToArray(m_InstancesDict.Values); - } + foreach (XMRInstance ins in instanceArray) { // Don't save attachments @@ -1856,8 +1796,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { ArrayList errors; - lock (m_ScriptErrors) { - while (!m_ScriptErrors.TryGetValue (itemID, out errors)) { + lock (m_ScriptErrors) + { + while (!m_ScriptErrors.TryGetValue (itemID, out errors)) + { Monitor.Wait (m_ScriptErrors); } m_ScriptErrors.Remove (itemID); @@ -1871,13 +1813,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public Dictionary GetObjectScriptsExecutionTimes () { Dictionary topScripts = new Dictionary (); - lock (m_InstancesDict) { - foreach (XMRInstance instance in m_InstancesDict.Values) { + lock (m_InstancesDict) + { + foreach (XMRInstance instance in m_InstancesDict.Values) + { uint rootLocalID = instance.m_Part.ParentGroup.LocalId; float oldTotal; - if (!topScripts.TryGetValue (rootLocalID, out oldTotal)) { + if (!topScripts.TryGetValue (rootLocalID, out oldTotal)) oldTotal = 0; - } + topScripts[rootLocalID] = (float)instance.m_CPUTime + oldTotal; } } @@ -1892,15 +1836,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ public float GetScriptExecutionTime (List itemIDs) { - if ((itemIDs == null) || (itemIDs.Count == 0)) { + if ((itemIDs == null) || (itemIDs.Count == 0)) return 0; - } + float time = 0; - foreach (UUID itemID in itemIDs) { + foreach (UUID itemID in itemIDs) + { XMRInstance instance = GetInstance (itemID); - if ((instance != null) && instance.Running) { + if ((instance != null) && instance.Running) time += (float) instance.m_CPUTime; - } } return time; } @@ -1911,7 +1855,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public void SuspendScript(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) + { TraceCalls("[XMREngine]: XMREngine.SuspendScript({0})", itemID.ToString()); instance.SuspendIt(); } @@ -1923,10 +1868,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public void ResumeScript(UUID itemID) { XMRInstance instance = GetInstance (itemID); - if (instance != null) { + if (instance != null) + { TraceCalls("[XMREngine]: XMREngine.ResumeScript({0})", itemID.ToString()); instance.ResumeIt(); - } else { + } + else + { // probably an XEngine script } } @@ -1939,13 +1887,17 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { List itemIDList = m_ObjectItemList[partUUID]; int n = 0; - foreach (UUID itemID in itemIDList) { - if (m_InstancesDict.ContainsKey (itemID)) n ++; + foreach (UUID itemID in itemIDList) + { + if (m_InstancesDict.ContainsKey(itemID)) + n ++; } XMRInstance[] a = new XMRInstance[n]; n = 0; - foreach (UUID itemID in itemIDList) { - if (m_InstancesDict.TryGetValue (itemID, out a[n])) n ++; + foreach (UUID itemID in itemIDList) + { + if (m_InstancesDict.TryGetValue (itemID, out a[n])) + n ++; } m_ObjectInstArray[partUUID] = a; return a; @@ -1953,11 +1905,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine public void TraceCalls (string format, params object[] args) { - if (m_TraceCalls) m_log.DebugFormat (format, args); + if (m_TraceCalls) + m_log.DebugFormat (format, args); } public void Verbose (string format, params object[] args) { - if (m_Verbose) m_log.DebugFormat (format, args); + if (m_Verbose) + m_log.DebugFormat (format, args); } /** diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs index fdf65cfbbf..0e7d3038e9 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRHeapTracker.cs @@ -119,6 +119,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine //FAST: return ++ counter; // VS2017 in debug mode seems content to run this quickly though: + try { return lis.Size; } catch { diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs index fbdf1bf90c..82759eecbd 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstAbstract.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Reflection.Emit; -using System.Runtime.Serialization; using System.Text; using System.Threading; diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs index d9c578ae4f..1cf1ad15e5 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRInstCtor.cs @@ -78,9 +78,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine if (stackSize < 16384) stackSize = 16384; if (heapSize < 16384) heapSize = 16384; - /* - * Save all call parameters in instance vars for easy access. - */ + // Save all call parameters in instance vars for easy access. m_Engine = engine; m_ScriptBasePath = scriptBasePath; m_StackSize = stackSize; @@ -88,185 +86,167 @@ namespace OpenSim.Region.ScriptEngine.XMREngine m_CompilerErrors = errors; m_StateFileName = GetStateFileName(scriptBasePath, m_ItemID); - /* - * Not in any XMRInstQueue. - */ + // Not in any XMRInstQueue. m_NextInst = this; m_PrevInst = this; - /* - * Set up list of API calls it has available. - * This also gets the API modules ready to accept setup data, such as - * active listeners being restored. - */ + // Set up list of API calls it has available. + // This also gets the API modules ready to accept setup data, such as + // active listeners being restored. IScriptApi scriptApi; ApiManager am = new ApiManager(); foreach (string api in am.GetApis()) { - /* - * Instantiate the API for this script instance. - */ + // Instantiate the API for this script instance. if (api != "LSL") { scriptApi = am.CreateApi(api); } else { scriptApi = m_XMRLSLApi = new XMRLSL_Api(); } - /* - * Connect it up to the instance. - */ + // Connect it up to the instance. InitScriptApi (engine, api, scriptApi); } m_XMRLSLApi.InitXMRLSLApi(this); - /* - * Get object loaded, compiling script and reading .state file as - * necessary to restore the state. - */ + // Get object loaded, compiling script and reading .state file as + // necessary to restore the state. suspendOnCheckRunHold = true; InstantiateScript(); m_SourceCode = null; if (m_ObjCode == null) throw new ArgumentNullException ("m_ObjCode"); - if (m_ObjCode.scriptEventHandlerTable == null) { + if (m_ObjCode.scriptEventHandlerTable == null) throw new ArgumentNullException ("m_ObjCode.scriptEventHandlerTable"); - } suspendOnCheckRunHold = false; suspendOnCheckRunTemp = false; - /* - * Declare which events the script's current state can handle. - */ + // Declare which events the script's current state can handle. int eventMask = GetStateEventFlags(stateCode); m_Part.SetScriptEvents(m_ItemID, eventMask); } private void InitScriptApi (XMREngine engine, string api, IScriptApi scriptApi) { - /* - * Set up m_ApiManager_ = instance pointer. - */ + // Set up m_ApiManager_ = instance pointer. engine.m_XMRInstanceApiCtxFieldInfos[api].SetValue (this, scriptApi); - /* - * Initialize the API instance. - */ + // Initialize the API instance. scriptApi.Initialize(m_Engine, m_Part, m_Item); this.InitApi (api, scriptApi); } - - // Get script object code loaded in memory and all ready to run, - // ready to resume it from where the .state file says it was last + /* + * Get script object code loaded in memory and all ready to run, + * ready to resume it from where the .state file says it was last + */ private void InstantiateScript() { bool compiledIt = false; ScriptObjCode objCode; - /* - * If source code string is empty, use the asset ID as the object file name. - * Allow lines of // comments at the beginning (for such as engine selection). - */ + // If source code string is empty, use the asset ID as the object file name. + // Allow lines of // comments at the beginning (for such as engine selection). int i, j, len; if (m_SourceCode == null) m_SourceCode = String.Empty; - for (len = m_SourceCode.Length; len > 0; -- len) { - if (m_SourceCode[len-1] > ' ') break; + for (len = m_SourceCode.Length; len > 0; --len) + { + if (m_SourceCode[len-1] > ' ') + break; } - for (i = 0; i < len; i ++) { + for (i = 0; i < len; i ++) + { char c = m_SourceCode[i]; - if (c <= ' ') continue; - if (c != '/') break; - if ((i + 1 >= len) || (m_SourceCode[i+1] != '/')) break; + if (c <= ' ') + continue; + if (c != '/') + break; + if ((i + 1 >= len) || (m_SourceCode[i+1] != '/')) + break; i = m_SourceCode.IndexOf ('\n', i); - if (i < 0) i = len - 1; + if (i < 0) + i = len - 1; } - if ((i >= len) || !m_Engine.m_UseSourceHashCode) { - - /* - * Source consists of nothing but // comments and whitespace, - * or we are being forced to use the asset-id as the key, to - * open an already existing object code file. - */ + if ((i >= len) || !m_Engine.m_UseSourceHashCode) + { + // Source consists of nothing but // comments and whitespace, + // or we are being forced to use the asset-id as the key, to + // open an already existing object code file. m_ScriptObjCodeKey = m_Item.AssetID.ToString (); - if (i >= len) m_SourceCode = ""; - } else { - - /* - * Make up dictionary key for the object code. - * Use the same object code for identical source code - * regardless of asset ID, so we don't care if they - * copy scripts or not. - */ + if (i >= len) + m_SourceCode = ""; + } + else + { + // Make up dictionary key for the object code. + // Use the same object code for identical source code + // regardless of asset ID, so we don't care if they + // copy scripts or not. byte[] scbytes = System.Text.Encoding.UTF8.GetBytes (m_SourceCode); StringBuilder sb = new StringBuilder ((256 + 5) / 6); ByteArrayToSixbitStr (sb, System.Security.Cryptography.SHA256.Create ().ComputeHash (scbytes)); m_ScriptObjCodeKey = sb.ToString (); - /* - * But source code can be just a sixbit string itself - * that identifies an already existing object code file. - */ - if (len - i == m_ScriptObjCodeKey.Length) { - for (j = len; -- j >= i;) { - if (sixbit.IndexOf (m_SourceCode[j]) < 0) break; + // But source code can be just a sixbit string itself + // that identifies an already existing object code file. + if (len - i == m_ScriptObjCodeKey.Length) + { + for (j = len; -- j >= i;) + { + if (sixbit.IndexOf (m_SourceCode[j]) < 0) + break; } - if (j < i) { + if (j < i) + { m_ScriptObjCodeKey = m_SourceCode.Substring (i, len - i); m_SourceCode = ""; } } } - /* - * There may already be an ScriptObjCode struct in memory that - * we can use. If not, try to compile it. - */ - lock (m_CompileLock) { - if (!m_CompiledScriptObjCode.TryGetValue (m_ScriptObjCodeKey, out objCode) || m_ForceRecomp) { + // There may already be an ScriptObjCode struct in memory that + // we can use. If not, try to compile it. + lock (m_CompileLock) + { + if (!m_CompiledScriptObjCode.TryGetValue (m_ScriptObjCodeKey, out objCode) || m_ForceRecomp) + { objCode = TryToCompile (); compiledIt = true; } - /* - * Loaded successfully, increment reference count. - * - * If we just compiled it though, reset count to 0 first as - * this is the one-and-only existance of this objCode struct, - * and we want any old ones for this source code to be garbage - * collected. - */ - if (compiledIt) { + // Loaded successfully, increment reference count. + + // If we just compiled it though, reset count to 0 first as + // this is the one-and-only existance of this objCode struct, + // and we want any old ones for this source code to be garbage + // collected. + + if (compiledIt) + { m_CompiledScriptObjCode[m_ScriptObjCodeKey] = objCode; objCode.refCount = 0; } objCode.refCount ++; - /* - * Now set up to decrement ref count on dispose. - */ + // Now set up to decrement ref count on dispose. m_ObjCode = objCode; } - try { - - /* - * Fill in script instance from object code - * Script instance is put in a "never-ever-has-run-before" state. - */ + try + { + // Fill in script instance from object code + // Script instance is put in a "never-ever-has-run-before" state. LoadObjCode(); - /* - * Fill in script intial state - * - either as loaded from a .state file - * - or initial default state_entry() event - */ + // Fill in script intial state + // - either as loaded from a .state file + // - or initial default state_entry() event LoadInitialState(); - } catch { - - /* - * If any error loading, decrement object code reference count. - */ + } + catch + { + // If any error loading, decrement object code reference count. DecObjCodeRefCount (); throw; } @@ -277,42 +257,41 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { int bit = 0; int val = 0; - foreach (byte b in bytes) { + foreach (byte b in bytes) + { val |= (int)((uint)b << bit); bit += 8; - while (bit >= 6) { + while (bit >= 6) + { sb.Append (sixbit[val&63]); val >>= 6; bit -= 6; } } - if (bit > 0) { + if (bit > 0) sb.Append (sixbit[val&63]); - } } - // Try to create object code from source code - // If error, just throw exception + /* + * Try to create object code from source code + * If error, just throw exception + */ private ScriptObjCode TryToCompile () { m_CompilerErrors.Clear(); - /* - * If object file exists, create ScriptObjCode directly from that. - * Otherwise, compile the source to create object file then create - * ScriptObjCode from that. - */ + // If object file exists, create ScriptObjCode directly from that. + // Otherwise, compile the source to create object file then create + // ScriptObjCode from that. + string assetID = m_Item.AssetID.ToString(); m_CameFrom = "asset://" + assetID; ScriptObjCode objCode = Compile (); if (m_CompilerErrors.Count != 0) - { throw new Exception ("compilation errors"); - } + if (objCode == null) - { throw new Exception ("compilation failed"); - } return objCode; } @@ -323,18 +302,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private string FetchSource (string cameFrom) { m_log.Debug ("[XMREngine]: fetching source " + cameFrom); - if (!cameFrom.StartsWith ("asset://")) { + if (!cameFrom.StartsWith ("asset://")) throw new Exception ("unable to retrieve source from " + cameFrom); - } + string assetID = cameFrom.Substring (8); AssetBase asset = m_Engine.World.AssetService.Get(assetID); - if (asset == null) { + if (asset == null) throw new Exception ("source not found " + cameFrom); - } + string source = Encoding.UTF8.GetString (asset.Data); - if (EmptySource (source)) { + if (EmptySource (source)) throw new Exception ("fetched source empty " + cameFrom); - } + return source; } @@ -344,53 +323,47 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ private void LoadObjCode () { - /* - * Script must leave this much stack remaining on calls to CheckRun(). - */ + // Script must leave this much stack remaining on calls to CheckRun(). + this.stackLimit = m_StackSize / 2; - /* - * This is how many total heap bytes script is allowed to use. - */ + // This is how many total heap bytes script is allowed to use. this.heapLimit = m_HeapSize; - /* - * Allocate global variable arrays. - */ + // Allocate global variable arrays. this.glblVars.AllocVarArrays (m_ObjCode.glblSizes); - /* - * Script can handle these event codes. - */ + // Script can handle these event codes. m_HaveEventHandlers = new bool[m_ObjCode.scriptEventHandlerTable.GetLength(1)]; - for (int i = m_ObjCode.scriptEventHandlerTable.GetLength(0); -- i >= 0;) { - for (int j = m_ObjCode.scriptEventHandlerTable.GetLength(1); -- j >= 0;) { - if (m_ObjCode.scriptEventHandlerTable[i,j] != null) { + for (int i = m_ObjCode.scriptEventHandlerTable.GetLength(0); -- i >= 0;) + { + for (int j = m_ObjCode.scriptEventHandlerTable.GetLength(1); -- j >= 0;) + { + if (m_ObjCode.scriptEventHandlerTable[i,j] != null) + { m_HaveEventHandlers[j] = true; } } } - /* - * Set up microthread object which actually calls the script event handler functions. - */ + // Set up microthread object which actually calls the script event handler functions. this.microthread = (IScriptUThread)m_Engine.uThreadCtor.Invoke (new object[] { this }); } - // LoadInitialState() - // if no state XML file exists for the asset, - // post initial default state events - // else - // try to restore from .state file - // If any error, throw exception - // + /* + * LoadInitialState() + * if no state XML file exists for the asset, + * post initial default state events + * else + * try to restore from .state file + * If any error, throw exception + */ private void LoadInitialState() { - /* - * If no .state file exists, start from default state - * Otherwise, read initial state from the .state file - */ - if (!File.Exists(m_StateFileName)) { + // If no .state file exists, start from default state + // Otherwise, read initial state from the .state file + if (!File.Exists(m_StateFileName)) + { m_Running = true; // event processing is enabled eventCode = ScriptEventCode.None; // not processing any event @@ -401,7 +374,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine PostEvent(new EventParams("state_entry", zeroObjectArray, zeroDetectParams)); - } else { + } + else + { FileStream fs = File.Open(m_StateFileName, FileMode.Open, FileAccess.Read); @@ -415,31 +390,29 @@ namespace OpenSim.Region.ScriptEngine.XMREngine LoadScriptState(doc); } - /* - * Post event(s) saying what caused the script to start. - */ - if (m_PostOnRez) { + // Post event(s) saying what caused the script to start. + if (m_PostOnRez) + { PostEvent(new EventParams("on_rez", new Object[] { m_StartParam }, zeroDetectParams)); } - switch (m_StateSource) { - case StateSource.AttachedRez: { + switch (m_StateSource) + { + case StateSource.AttachedRez: // PostEvent(new EventParams("attach", // new object[] { m_Part.ParentGroup.AttachedAvatar.ToString() }, // zeroDetectParams)); break; - } - case StateSource.PrimCrossing: { + case StateSource.PrimCrossing: PostEvent(new EventParams("changed", sbcCR, zeroDetectParams)); break; - } - case StateSource.Teleporting: { + case StateSource.Teleporting: PostEvent(new EventParams("changed", sbcCR, zeroDetectParams)); @@ -447,14 +420,12 @@ namespace OpenSim.Region.ScriptEngine.XMREngine sbcCT, zeroDetectParams)); break; - } - case StateSource.RegionStart: { + case StateSource.RegionStart: PostEvent(new EventParams("changed", sbcCRS, zeroDetectParams)); break; - } } } @@ -468,17 +439,19 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ private void ErrorHandler(Token token, string message) { - if (token != null) { + if (token != null) + { string srcloc = token.SrcLoc; - if (srcloc.StartsWith (m_CameFrom)) { + if (srcloc.StartsWith (m_CameFrom)) srcloc = srcloc.Substring (m_CameFrom.Length); - } + m_CompilerErrors.Add(srcloc + " Error: " + message); - } else if (message != null) { - m_CompilerErrors.Add("(0,0) Error: " + message); - } else { - m_CompilerErrors.Add("(0,0) Error compiling, see exception in log"); } + else if (message != null) + m_CompilerErrors.Add("(0,0) Error: " + message); + + else + m_CompilerErrors.Add("(0,0) Error compiling, see exception in log"); } /** @@ -503,28 +476,25 @@ namespace OpenSim.Region.ScriptEngine.XMREngine // Everything we know is enclosed in ... XmlElement scriptStateN = (XmlElement)doc.SelectSingleNode("ScriptState"); - if (scriptStateN == null) { + if (scriptStateN == null) throw new Exception("no tag"); - } + string sen = scriptStateN.GetAttribute("Engine"); - if ((sen == null) || (sen != m_Engine.ScriptEngineName)) { + if ((sen == null) || (sen != m_Engine.ScriptEngineName)) throw new Exception(" missing Engine=\"XMREngine\" attribute"); - } + // AssetID is unique for the script source text so make sure the // state file was written for that source file string assetID = scriptStateN.GetAttribute("Asset"); if (assetID != m_Item.AssetID.ToString()) - { throw new Exception(" assetID mismatch"); - } // Also match the sourceHash in case script was // loaded via 'xmroption fetchsource' and has changed string sourceHash = scriptStateN.GetAttribute ("SourceHash"); - if ((sourceHash == null) || (sourceHash != m_ObjCode.sourceHash)) { + if ((sourceHash == null) || (sourceHash != m_ObjCode.sourceHash)) throw new Exception (" SourceHash mismatch"); - } // Get various attributes XmlElement runningN = (XmlElement)scriptStateN.SelectSingleNode("Running"); @@ -549,8 +519,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine Object[] pluginData = ExtractXMLObjectArray(pluginN, "plugin"); // Script's global variables and stack contents - XmlElement snapshotN = - (XmlElement)scriptStateN.SelectSingleNode("Snapshot"); + XmlElement snapshotN = (XmlElement)scriptStateN.SelectSingleNode("Snapshot"); Byte[] data = Convert.FromBase64String(snapshotN.InnerText); MemoryStream ms = new MemoryStream(); @@ -561,18 +530,21 @@ namespace OpenSim.Region.ScriptEngine.XMREngine // Restore event queues, preserving any events that queued // whilst we were restoring the state - lock (m_QueueLock) { + lock (m_QueueLock) + { m_DetectParams = detParams; - foreach (EventParams evt in m_EventQueue) { + foreach (EventParams evt in m_EventQueue) eventQueue.AddLast (evt); - } - m_EventQueue = eventQueue; - for (int i = m_EventCounts.Length; -- i >= 0;) m_EventCounts[i] = 0; + + m_EventQueue = eventQueue; + for (int i = m_EventCounts.Length; -- i >= 0;) + m_EventCounts[i] = 0; + foreach (EventParams evt in m_EventQueue) { - ScriptEventCode eventCode = (ScriptEventCode)Enum.Parse (typeof (ScriptEventCode), + ScriptEventCode eventCode = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), evt.EventName); - m_EventCounts[(int)eventCode] ++; + m_EventCounts[(int)eventCode]++; } } @@ -594,7 +566,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private LinkedList RestoreEventQueue(XmlNode eventsN) { LinkedList eventQueue = new LinkedList(); - if (eventsN != null) { + if (eventsN != null) + { XmlNodeList eventL = eventsN.SelectNodes("Event"); foreach (XmlNode evnt in eventL) { @@ -629,8 +602,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine XmlNodeList detectL = detectedN.SelectNodes("DetectParams"); DetectParams detprm = new DetectParams(); - foreach (XmlNode detxml in detectL) { - try { + foreach (XmlNode detxml in detectL) + { + try + { detprm.Group = new UUID(detxml.Attributes.GetNamedItem("group").Value); detprm.Key = new UUID(detxml.Attributes.GetNamedItem("key").Value); detprm.Owner = new UUID(detxml.Attributes.GetNamedItem("owner").Value); @@ -648,7 +623,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine detected.Add(detprm); detprm = new DetectParams(); - } catch (Exception e) { + } + catch (Exception e) + { m_log.Warn("[XMREngine]: RestoreDetectParams bad XML: " + detxml.ToString()); m_log.Warn("[XMREngine]: ... " + e.ToString()); } @@ -670,9 +647,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine XmlNodeList itemL = parent.SelectNodes(tag); foreach (XmlNode item in itemL) - { olist.Add(ExtractXMLObjectValue(item)); - } return olist.ToArray(); } @@ -682,9 +657,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine string itemType = item.Attributes.GetNamedItem("type").Value; if (itemType == "list") - { return new LSL_List(ExtractXMLObjectArray(item, "item")); - } if (itemType == "OpenMetaverse.UUID") { @@ -701,9 +674,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine string assembly = itemType + ", OpenSim.Region.ScriptEngine.Shared"; itemT = Type.GetType(assembly); if (itemT == null) - { return null; - } + return Activator.CreateInstance(itemT, args); } @@ -724,77 +696,82 @@ namespace OpenSim.Region.ScriptEngine.XMREngine miehstream = stream; XMRScriptThread cst = XMRScriptThread.CurrentScriptThread (); - if (cst != null) { - + if (cst != null) + { // in case we are getting called inside some LSL Api function MigrateInEventHandlerThread (); - } else { - + } + else + { // some other thread, do migration via a script thread - lock (XMRScriptThread.m_WakeUpLock) { + lock (XMRScriptThread.m_WakeUpLock) + { m_Engine.m_ThunkQueue.Enqueue (this.MigrateInEventHandlerThread); } XMRScriptThread.WakeUpOne (); // wait for it to complete - lock (miehdone) { - while (miehstream != null) { - Monitor.Wait (miehdone); - } + lock (miehdone) + { + while (miehstream != null) + Monitor.Wait(miehdone); } } // maybe it threw up - if (miehexcep != null) throw miehexcep; + if (miehexcep != null) + throw miehexcep; } + private Exception miehexcep; private object miehdone = new object (); private Stream miehstream; private void MigrateInEventHandlerThread () { - try { + try + { int mv = miehstream.ReadByte (); - if (mv != migrationVersion) { + if (mv != migrationVersion) throw new Exception ("incoming migration version " + mv + " but accept only " + migrationVersion); - } + miehstream.ReadByte (); // ignored - /* - * Restore script variables and stack and other state from stream. - * And it also marks us busy (by setting this.eventCode) so we can't be - * started again and this event lost. - */ + // Restore script variables and stack and other state from stream. + // And it also marks us busy (by setting this.eventCode) so we can't be + // started again and this event lost. + BinaryReader br = new BinaryReader (miehstream); this.MigrateIn (br); - /* - * If eventCode is None, it means the script was idle when migrated. - */ - if (this.eventCode != ScriptEventCode.None) { + // If eventCode is None, it means the script was idle when migrated. + + if (this.eventCode != ScriptEventCode.None) + { + // So microthread.Start() calls XMRScriptUThread.Main() which calls the + // event handler function. The event handler function sees the stack + // frames in this.stackFrames and restores its args and locals, then calls + // whatever it was calling when the snapshot was taken. That function also + // sees this.stackFrames and restores its args and locals, and so on... + // Eventually it gets to the point of calling CheckRun() which sees we are + // doing a restore and it suspends, returning here with the microthread + // stack all restored. It shouldn't ever throw an exception. - /* - * So microthread.Start() calls XMRScriptUThread.Main() which calls the - * event handler function. The event handler function sees the stack - * frames in this.stackFrames and restores its args and locals, then calls - * whatever it was calling when the snapshot was taken. That function also - * sees this.stackFrames and restores its args and locals, and so on... - * Eventually it gets to the point of calling CheckRun() which sees we are - * doing a restore and it suspends, returning here with the microthread - * stack all restored. It shouldn't ever throw an exception. - */ this.stackFramesRestored = false; Exception te = microthread.StartEx (); if (te != null) throw te; - if (!this.stackFramesRestored) throw new Exception ("migrate in did not complete"); + if (!this.stackFramesRestored) + throw new Exception ("migrate in did not complete"); } - } catch (Exception e) { + } + catch (Exception e) + { miehexcep = e; - } finally { - - /* - * Wake the MigrateInEventHandler() method above. - */ - lock (miehdone) { + } + finally + { + // Wake the MigrateInEventHandler() method above. + lock (miehdone) + { miehstream = null; Monitor.Pulse (miehdone); } @@ -807,67 +784,67 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ public string CheckFetchbinaryAllowed () { - string ownerPerm = m_Engine.Config.GetString ("Allow_fetchbinary", ""); + string ownerPerm = m_Engine.Config.GetString ("Allow_fetchbinary", ""); UUID ownerID = m_Item.OwnerID; string[] ids = ownerPerm.Split (new char[] { ',' }); - foreach (string id in ids) { - string curuc = id.Trim ().ToUpperInvariant (); + foreach (string id in ids) + { + string curuc = id.Trim().ToUpperInvariant(); - switch (curuc) { - case "ESTATE_MANAGER": { + switch (curuc) + { + case "ESTATE_MANAGER": if (m_Engine.m_Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner (ownerID) && - (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner != ownerID)) { + (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner != ownerID)) return null; - } - break; - } - case "ESTATE_OWNER": { - if (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner == ownerID) { + break; + + case "ESTATE_OWNER": + if (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner == ownerID) return null; - } - break; - } - case "PARCEL_GROUP_MEMBER": { + break; + + case "PARCEL_GROUP_MEMBER": ILandObject land = m_Engine.m_Scene.LandChannel.GetLandObject (m_Part.AbsolutePosition); - if (land.LandData.GroupID == m_Item.GroupID && land.LandData.GroupID != UUID.Zero) { + if (land.LandData.GroupID == m_Item.GroupID && land.LandData.GroupID != UUID.Zero) return null; - } - break; - } - case "PARCEL_OWNER": { - ILandObject land = m_Engine.m_Scene.LandChannel.GetLandObject (m_Part.AbsolutePosition); - if (land.LandData.OwnerID == ownerID) { + break; + + case "PARCEL_OWNER": + ILandObject Oland = m_Engine.m_Scene.LandChannel.GetLandObject (m_Part.AbsolutePosition); + if (Oland.LandData.OwnerID == ownerID) return null; - } - break; - } - case "TRUE": { + break; + + case "TRUE": return null; - } - default: { + default: UUID uuid; - if (UUID.TryParse (curuc, out uuid)) { + if (UUID.TryParse (curuc, out uuid)) if (uuid == ownerID) return null; - } + break; - } } } string creatorPerm = m_Engine.Config.GetString ("Creators_fetchbinary", ""); UUID creatorID = m_Item.CreatorID; ids = creatorPerm.Split (new char[] { ',' }); - foreach (string id in ids) { + foreach (string id in ids) + { string current = id.Trim (); UUID uuid; - if (UUID.TryParse (current, out uuid)) { - if (uuid != UUID.Zero) { - if (creatorID == uuid) return null; + if (UUID.TryParse (current, out uuid)) + { + if (uuid != UUID.Zero) + { + if (creatorID == uuid) + return null; } } } diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs index ddb3698008..6470477579 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptThread.cs @@ -25,7 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using Mono.Tasklets; using OpenSim.Framework.Monitoring; using System; using System.Collections.Generic; @@ -70,7 +69,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private bool m_Exiting = false; private bool m_SuspendScriptThreadFlag = false; private bool m_WakeUpThis = false; - private bool m_Continuations = false; public DateTime m_LastRanAt = DateTime.MinValue; public int m_ScriptThreadTID = 0; public long m_ScriptExecTime = 0; @@ -78,15 +76,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private XMREngine engine; public XMRInstance m_RunInstance = null; - public XMRScriptThread(XMREngine eng) + public XMRScriptThread(XMREngine eng, int i) { engine = eng; - m_Continuations = engine.uThreadCtor.DeclaringType == typeof (ScriptUThread_Con); -// thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.BelowNormal); - thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.Normal); + if(i < 0) + thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.Normal); + else + thd = XMREngine.StartMyThread (RunScriptThread, "xmrengineExec" + i.ToString(), ThreadPriority.Normal); lock (m_AllThreads) m_AllThreads.Add (thd, this); - } public void SuspendThread() @@ -125,7 +123,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine */ private void WakeUpScriptThread() { - lock (m_WakeUpLock) { + lock (m_WakeUpLock) + { m_WakeUpThis = true; Monitor.PulseAll (m_WakeUpLock); } @@ -137,24 +136,22 @@ namespace OpenSim.Region.ScriptEngine.XMREngine private void RunScriptThread() { XMRInstance inst; - Mono.Tasklets.Continuation engstack = null; - if (m_Continuations) { - engstack = new Mono.Tasklets.Continuation (); - engstack.Mark (); - } m_ScriptThreadTID = System.Threading.Thread.CurrentThread.ManagedThreadId; - while (!m_Exiting) { + while (!m_Exiting) + { XMREngine.UpdateMyThread (); /* * Handle 'xmr resume/suspend' commands. */ - if (m_SuspendScriptThreadFlag) { + if (m_SuspendScriptThreadFlag) + { lock (m_WakeUpLock) { while (m_SuspendScriptThreadFlag && !m_Exiting && - (engine.m_ThunkQueue.Count == 0)) { + (engine.m_ThunkQueue.Count == 0)) + { Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); XMREngine.UpdateMyThread (); } @@ -165,81 +162,72 @@ namespace OpenSim.Region.ScriptEngine.XMREngine * Maybe there are some scripts waiting to be migrated in or out. */ ThreadStart thunk = null; - lock (m_WakeUpLock) { - if (engine.m_ThunkQueue.Count > 0) { + lock (m_WakeUpLock) + { + if (engine.m_ThunkQueue.Count > 0) thunk = engine.m_ThunkQueue.Dequeue (); - } } - if (thunk != null) { + if (thunk != null) + { inst = (XMRInstance)thunk.Target; - if (m_Continuations && (inst.scrstack == null)) { - inst.engstack = engstack; - inst.scrstack = new Mono.Tasklets.Continuation (); - inst.scrstack.Mark (); - } thunk (); continue; } - if (engine.m_StartProcessing) { + if (engine.m_StartProcessing) + { + // If event just queued to any idle scripts + // start them right away. But only start so + // many so we can make some progress on yield + // queue. - /* - * If event just queued to any idle scripts - * start them right away. But only start so - * many so we can make some progress on yield - * queue. - */ int numStarts; - for (numStarts = 5; -- numStarts >= 0;) { - lock (engine.m_StartQueue) { + for (numStarts = 5; -- numStarts >= 0;) + { + lock (engine.m_StartQueue) + { inst = engine.m_StartQueue.RemoveHead(); } if (inst == null) break; if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state"); - if (m_Continuations && (inst.scrstack == null)) { - inst.engstack = engstack; - inst.scrstack = new Mono.Tasklets.Continuation (); - inst.scrstack.Mark (); - } RunInstance (inst); } - /* - * If there is something to run, run it - * then rescan from the beginning in case - * a lot of things have changed meanwhile. - * - * These are considered lower priority than - * m_StartQueue as they have been taking at - * least one quantum of CPU time and event - * handlers are supposed to be quick. - */ - lock (engine.m_YieldQueue) { + // If there is something to run, run it + // then rescan from the beginning in case + // a lot of things have changed meanwhile. + // + // These are considered lower priority than + // m_StartQueue as they have been taking at + // least one quantum of CPU time and event + // handlers are supposed to be quick. + + lock (engine.m_YieldQueue) + { inst = engine.m_YieldQueue.RemoveHead(); } - if (inst != null) { + if (inst != null) + { if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state"); - RunInstance (inst); + RunInstance(inst); numStarts = -1; } - /* - * If we left something dangling in the m_StartQueue or m_YieldQueue, go back to check it. - */ - if (numStarts < 0) continue; + // If we left something dangling in the m_StartQueue or m_YieldQueue, go back to check it. + if (numStarts < 0) + continue; } - /* - * Nothing to do, sleep. - */ - lock (m_WakeUpLock) { - if (!m_WakeUpThis && (m_WakeUpOne <= 0) && !m_Exiting) { - Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); - } + // Nothing to do, sleep. + + lock (m_WakeUpLock) + { + if (!m_WakeUpThis && (m_WakeUpOne <= 0) && !m_Exiting) + Monitor.Wait(m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2); + m_WakeUpThis = false; - if ((m_WakeUpOne > 0) && (-- m_WakeUpOne > 0)) { + if ((m_WakeUpOne > 0) && (-- m_WakeUpOne > 0)) Monitor.Pulse (m_WakeUpLock); - } } } XMREngine.MyThreadExiting (); diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs index 2e290ddc46..74bba4f258 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs +++ b/OpenSim/Region/ScriptEngine/XMREngine/XMRScriptUThread.cs @@ -25,31 +25,24 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using Mono.Tasklets; using System; -using System.Collections.Generic; -using System.Reflection; -using System.Threading; - - /***************************\ * Use standard C# code * - * - uses system threads * + * - uses stack smashing * \***************************/ -namespace OpenSim.Region.ScriptEngine.XMREngine { +namespace OpenSim.Region.ScriptEngine.XMREngine +{ - public class ScriptUThread_Sys : IScriptUThread, IDisposable + public class ScriptUThread_Nul : IScriptUThread, IDisposable { - private Exception except; private int active; // -1: hibernating // 0: exited // 1: running - private object activeLock = new object (); private XMRInstance instance; - public ScriptUThread_Sys (XMRInstance instance) + public ScriptUThread_Nul (XMRInstance instance) { this.instance = instance; } @@ -63,31 +56,27 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { */ public Exception StartEx () { - lock (activeLock) { + // We should only be called when no event handler running. + if (active != 0) throw new Exception ("active=" + active); - /* - * We should only be called when script is inactive. - */ - if (active != 0) throw new Exception ("active=" + active); - - /* - * Tell CallSEHThread() to run script event handler in a thread. - */ - active = 1; - TredPoo.RunSomething (CallSEHThread); - - /* - * Wait for script to call Hiber() or for script to - * return back out to CallSEHThread(). - */ - while (active > 0) { - Monitor.Wait (activeLock); + // Start script event handler from very beginning. + active = 1; + Exception except = null; + instance.callMode = XMRInstance.CallMode_NORMAL; + try { + instance.CallSEH (); // run script event handler + active = 0; + } catch (StackHibernateException) { + if (instance.callMode != XMRInstance.CallMode_SAVE) { + throw new Exception ("callMode=" + instance.callMode); } + active = -1; // it is hibernating, can be resumed + } catch (Exception e) { + active = 0; + except = e; // threw exception, save for Start()/Resume() } - /* - * Return whether or not script threw an exception. - */ + // Return whether or not script threw an exception. return except; } @@ -98,31 +87,27 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { */ public Exception ResumeEx () { - lock (activeLock) { + // We should only be called when script is hibernating. + if (active >= 0) throw new Exception ("active=" + active); - /* - * We should only be called when script is hibernating. - */ - if (active >= 0) throw new Exception ("active=" + active); - - /* - * Tell Hiber() to return back to script. - */ - active = 1; - Monitor.PulseAll (activeLock); - - /* - * Wait for script to call Hiber() again or for script to - * return back out to CallSEHThread(). - */ - while (active > 0) { - Monitor.Wait (activeLock); + // Resume script from captured stack. + instance.callMode = XMRInstance.CallMode_RESTORE; + instance.suspendOnCheckRunTemp = true; + Exception except = null; + try { + instance.CallSEH (); // run script event handler + active = 0; + } catch (StackHibernateException) { + if (instance.callMode != XMRInstance.CallMode_SAVE) { + throw new Exception ("callMode=" + instance.callMode); } + active = -1; + } catch (Exception e) { + active = 0; + except = e; // threw exception, save for Start()/Resume() } - /* - * Return whether or not script threw an exception. - */ + // Return whether or not script threw an exception. return except; } @@ -130,241 +115,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { * @brief Script is being closed out. * Terminate thread asap. */ - public void Dispose () - { - lock (activeLock) { - instance = null; - Monitor.PulseAll (activeLock); - } - } - - /** - * @brief Determine if script is active. - * Returns: 0: nothing started or has returned - * Resume() must not be called - * Start() may be called - * Hiber() must not be called - * -1: thread has called Hiber() - * Resume() may be called - * Start() may be called - * Hiber() must not be called - * 1: thread is running - * Resume() must not be called - * Start() must not be called - * Hiber() may be called - */ - public int Active () - { - return active; - } - - /** - * @brief This thread executes the script event handler code. - */ - private void CallSEHThread () - { - lock (activeLock) { - if (active <= 0) throw new Exception ("active=" + active); - - except = null; // assume completion without exception - try { - instance.CallSEH (); // run script event handler - } catch (Exception e) { - except = e; // threw exception, save for Start()/Resume() - } - - active = 0; // tell Start() or Resume() we're done - Monitor.PulseAll (activeLock); - } - } - - /** - * @brief Called by the script event handler whenever it wants to hibernate. - */ - public void Hiber () - { - if (active <= 0) throw new Exception ("active=" + active); - - // tell Start() or Resume() we are hibernating - active = -1; - Monitor.PulseAll (activeLock); - - // wait for Resume() or Dispose() to be called - while ((active < 0) && (instance != null)) { - Monitor.Wait (activeLock); - } - - // don't execute any more script code, just exit - if (instance == null) { - throw new AbortedByDisposeException (); - } - } - - /** - * @brief Number of remaining stack bytes. - */ - public int StackLeft () - { - return 0x7FFFFFFF; - } - - public class AbortedByDisposeException : Exception, IXMRUncatchable { } - - /** - * @brief Pool of threads that run script event handlers. - */ - private class TredPoo { - private static readonly TimeSpan idleTimeSpan = new TimeSpan (0, 0, 1, 0, 0); // 1 minute - - private static int tredPooAvail = 0; - private static object tredPooLock = new object (); - private static Queue tredPooQueue = new Queue (); - - /** - * @brief Queue a function for execution in a system thread. - */ - public static void RunSomething (ThreadStart entry) - { - lock (tredPooLock) { - tredPooQueue.Enqueue (entry); - Monitor.Pulse (tredPooLock); - if (tredPooAvail < tredPooQueue.Count) { - new TredPoo (); - } - } - } - - /** - * @brief Start a new system thread. - * It will shortly attempt to dequeue work or if none, - * add itself to the available thread list. - */ - private TredPoo () - { - Thread thread = new Thread (Main); - thread.Name = "XMRUThread_sys"; - thread.IsBackground = true; - thread.Start (); - tredPooAvail ++; - } - - /** - * @brief Executes items from the queue or waits a little while - * if nothing. If idle for a while, it exits. - */ - private void Main () - { - int first = 1; - ThreadStart entry; - while (true) { - lock (tredPooLock) { - tredPooAvail -= first; - first = 0; - while (tredPooQueue.Count <= 0) { - tredPooAvail ++; - bool keepgoing = Monitor.Wait (tredPooLock, idleTimeSpan); - -- tredPooAvail; - if (!keepgoing) return; - } - entry = tredPooQueue.Dequeue (); - } - entry (); - } - } - } - } -} - - - -/*************************************\ - * Use Mono.Tasklets.Continuations * - * - memcpy's stack * -\*************************************/ - -namespace OpenSim.Region.ScriptEngine.XMREngine { - - public partial class XMRInstance { - public Mono.Tasklets.Continuation engstack; - public Mono.Tasklets.Continuation scrstack; - } - - public class ScriptUThread_Con : IScriptUThread, IDisposable - { - private XMRInstance instance; - - public ScriptUThread_Con (XMRInstance instance) - { - this.instance = instance; - } - - private const int SAVEENGINESTACK = 0; - private const int LOADENGINESTACK = 1; - private const int SAVESCRIPTSTACK = 2; - private const int LOADSCRIPTSTACK = 3; - - private Exception except; - private int active; - - /** - * @brief Start script event handler from the beginning. - * Return when either the script event handler completes - * or the script calls Hiber(). - * @returns null: script did not throw any exception so far - * else: script threw an exception - */ - public Exception StartEx () - { - /* - * Save engine stack so we know how to jump back to engine in case - * the script calls Hiber(). - */ - switch (instance.engstack.Store (SAVEENGINESTACK)) { - - /* - * Engine stack has been saved, start running the event handler. - */ - case SAVEENGINESTACK: { - - /* - * Run event handler according to stackFrames. - * In either case it is assumed that stateCode and eventCode - * indicate which event handler is to be called and that ehArgs - * points to the event handler argument list. - */ - active = 1; - except = null; - try { - instance.CallSEH (); - } catch (Exception e) { - except = e; - } - - /* - * We now want to return to the script engine. - * Setting active = 0 means the microthread has exited. - * We need to call engstack.Restore() in case the script called Hiber() - * anywhere, we want to return out the corresponding Restore() and not the - * Start(). - */ - active = 0; - instance.engstack.Restore (LOADENGINESTACK); - throw new Exception ("returned from Restore()"); - } - - /* - * Script called Hiber() somewhere so just return back out. - */ - case LOADENGINESTACK: { - break; - } - - default: throw new Exception ("bad engstack code"); - } - - return except; - } - public void Dispose () { } @@ -389,75 +139,33 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { } /** - * @brief Called by the script wherever it wants to hibernate. - * So this means to save the scripts stack in 'instance.scrstack' then - * restore the engstack to cause us to return back to the engine. + * @brief Called by the script event handler whenever it wants to hibernate. */ public void Hiber () { - /* - * Save where we are in the script's code in 'instance.scrstack' - * so we can wake the script when Resume() is called. - */ - switch (instance.scrstack.Store (SAVESCRIPTSTACK)) { - - /* - * Script's stack is now saved in 'instance.scrstack'. - * Reload the engine's stack from 'instance.engstack' and jump to it. - */ - case SAVESCRIPTSTACK: { - active = -1; - instance.engstack.Restore (LOADENGINESTACK); - throw new Exception ("returned from Restore()"); - } - - /* - * Resume() was just called and we want to resume executing script code. - */ - case LOADSCRIPTSTACK: { - break; - } - - default: throw new Exception ("bad scrstack code"); + if (instance.callMode != XMRInstance.CallMode_NORMAL) { + throw new Exception ("callMode=" + instance.callMode); } - } - /** - * @brief We now want to run some more script code from where it last hibernated - * until it either finishes the script event handler or until the script - * calls Hiber() again. - */ - public Exception ResumeEx () - { - /* - * Save where we are in the engine's code in 'instance.engstack' - * so if the script calls Hiber() again or exits, we know how to get - * back to the engine. - */ - switch (instance.engstack.Store (SAVEENGINESTACK)) { + switch (active) { - /* - * This is original call to Resume() from the engine, - * jump to where we left off within Hiber(). - */ - case SAVEENGINESTACK: { + // the stack has been restored as a result of calling ResumeEx() + // say the microthread is now active and resume processing + case -1: { active = 1; - instance.scrstack.Restore (LOADSCRIPTSTACK); - throw new Exception ("returned from Restore()"); + return; } - /* - * Script has called Hiber() again, so return back to - * script engine code. - */ - case LOADENGINESTACK: { - break; + // the script event handler wants to hibernate + // capture stack frames and unwind to Start() or Resume() + case 1: { + instance.callMode = XMRInstance.CallMode_SAVE; + instance.stackFrames = null; + throw new StackHibernateException (); } - default: throw new Exception ("bad engstack code"); + default: throw new Exception ("active=" + active); } - - return except; } /** @@ -467,91 +175,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine { { return 0x7FFFFFFF; } + + public class StackHibernateException : Exception, IXMRUncatchable { } } } - - -/***********************************\ - * Use Mono.Tasklets.MMRUThreads * - * - switches stack pointer * -\***********************************/ - -namespace OpenSim.Region.ScriptEngine.XMREngine { - - public class ScriptUThread_MMR : IScriptUThread, IDisposable - { - private static Exception uthread_looked; - private static Type uttype; - private static Type uthread_entry; - private static MethodInfo uthread_dispose; - private static MethodInfo uthread_startex; - private static MethodInfo uthread_resumex; - private static MethodInfo uthread_suspend; - private static MethodInfo uthread_active; - private static MethodInfo uthread_stackleft; - - public static Exception LoadMono () - { - if ((uthread_looked == null) && (uthread_stackleft == null)) { - try { - Assembly mt = Assembly.Load ("Mono.Tasklets"); - uttype = mt.GetType ("Mono.Tasklets.MMRUThread", true); - uthread_entry = mt.GetType ("Mono.Tasklets.MMRUThread+Entry", true); - - uthread_dispose = uttype.GetMethod ("Dispose"); // no parameters, no return value - uthread_startex = uttype.GetMethod ("StartEx"); // takes uthread_entry delegate as parameter, returns exception - uthread_resumex = uttype.GetMethod ("ResumeEx"); // takes exception as parameter, returns exception - uthread_suspend = uttype.GetMethod ("Suspend", new Type[] { }); // no return value - uthread_active = uttype.GetMethod ("Active"); // no parameters, returns int - uthread_stackleft = uttype.GetMethod ("StackLeft"); // no parameters, returns IntPtr - } catch (Exception e) { - uthread_looked = new NotSupportedException ("'mmr' thread model requires patched mono", e); - } - } - return uthread_looked; - } - - private static object[] resumex_args = new object[] { null }; - - private object uthread; // type MMRUThread - private object[] startex_args = new object[1]; - - public ScriptUThread_MMR (XMRInstance instance) - { - this.uthread = Activator.CreateInstance (uttype, new object[] { (IntPtr) instance.m_StackSize, instance.m_DescName }); - startex_args[0] = Delegate.CreateDelegate (uthread_entry, instance, "CallSEH"); - } - - public void Dispose () - { - uthread_dispose.Invoke (uthread, null); - uthread = null; - } - - public Exception StartEx () - { - return (Exception) uthread_startex.Invoke (uthread, startex_args); - } - - public Exception ResumeEx () - { - return (Exception) uthread_resumex.Invoke (uthread, resumex_args); - } - - public void Hiber () - { - uthread_suspend.Invoke (null, null); - } - - public int Active () - { - return (int) uthread_active.Invoke (uthread, null); - } - - public int StackLeft () - { - return (int) (IntPtr) uthread_stackleft.Invoke (null, null); - } - } -} diff --git a/prebuild.xml b/prebuild.xml index 64236f9184..f6c1e46940 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2418,28 +2418,7 @@ - - - - - ../../../../bin/ - - - - - ../../../../bin/ - - - - ../../../../bin/ - - - - - - - - +