From 53a910e3e5add262a4fee1f73aad7419f9d150b5 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Wed, 7 Feb 2018 10:26:20 +0000 Subject: [PATCH] some more code from mrieker for system threads, give up of all the other mono dependent theading models only availble for linux (and possible not all platforms). This only has impact on micro-threading switching, and this only happens on long events and only every 60ms, aditionally we do remove a totally extra set of threads (that could grow in a uncontroled way on win) and their hanshake with main ones. This may of course be even more broken now :P --- .../XMREngine/MonoTaskletsDummy.cs | 55 - .../ScriptEngine/XMREngine/XMREngine.cs | 1062 ++++++++--------- .../ScriptEngine/XMREngine/XMRHeapTracker.cs | 1 + .../ScriptEngine/XMREngine/XMRInstAbstract.cs | 1 - .../ScriptEngine/XMREngine/XMRInstCtor.cs | 533 ++++----- .../ScriptEngine/XMREngine/XMRScriptThread.cs | 118 +- .../XMREngine/XMRScriptUThread.cs | 487 +------- prebuild.xml | 23 +- 8 files changed, 874 insertions(+), 1406 deletions(-) delete mode 100644 OpenSim/Region/ScriptEngine/XMREngine/MonoTaskletsDummy.cs 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/ - - - - - - - - +