try to fix xmr on multiregions per instance. Ugly spargetti ...; remove fixes for 2 llparcel functions that should not be needed; remove xmr own API, it has no business having one.

httptests
UbitUmarov 2018-02-07 19:52:18 +00:00
parent cddb848c13
commit 01ceb4d17e
8 changed files with 338 additions and 441 deletions

View File

@ -589,11 +589,11 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
* @brief Generate code for the usual ll...() functions.
*/
public class TokenDeclInline_BEApi : TokenDeclInline {
private static readonly MethodInfo fixLLParcelMediaQuery = ScriptCodeGen.GetStaticMethod
(typeof (XMRInstAbstract), "FixLLParcelMediaQuery", new Type[] { typeof (LSL_List) });
// private static readonly MethodInfo fixLLParcelMediaQuery = ScriptCodeGen.GetStaticMethod
// (typeof (XMRInstAbstract), "FixLLParcelMediaQuery", new Type[] { typeof (LSL_List) });
private static readonly MethodInfo fixLLParcelMediaCommandList = ScriptCodeGen.GetStaticMethod
(typeof (XMRInstAbstract), "FixLLParcelMediaCommandList", new Type[] { typeof (LSL_List) });
// private static readonly MethodInfo fixLLParcelMediaCommandList = ScriptCodeGen.GetStaticMethod
// (typeof (XMRInstAbstract), "FixLLParcelMediaCommandList", new Type[] { typeof (LSL_List) });
public bool doCheckRun;
private FieldInfo apiContextField;
@ -626,39 +626,41 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
*/
public override void CodeGen (ScriptCodeGen scg, Token errorAt, CompValuTemp result, CompValu[] args)
{
if (isTaggedCallsCheckRun) { // see if 'xmr' method that calls CheckRun() internally
new ScriptCodeGen.CallLabel (scg, errorAt); // if so, put a call label immediately before it
// .. so restoring the frame will jump immediately to the
// .. call without re-executing any code before this
if (isTaggedCallsCheckRun)
{ // see if 'xmr' method that calls CheckRun() internally
new ScriptCodeGen.CallLabel (scg, errorAt); // if so, put a call label immediately before it
// .. so restoring the frame will jump immediately to the
// .. call without re-executing any code before this
}
if (!methInfo.IsStatic) {
if (!methInfo.IsStatic)
{
scg.PushXMRInst (); // XMRInstanceSuperType pointer
if (apiContextField != null) {
if (apiContextField != null) // 'this' pointer for API function
scg.ilGen.Emit (errorAt, OpCodes.Ldfld, apiContextField);
// 'this' pointer for API function
}
}
for (int i = 0; i < args.Length; i ++) { // push arguments, boxing/unboxing as needed
for (int i = 0; i < args.Length; i ++) // push arguments, boxing/unboxing as needed
args[i].PushVal (scg, errorAt, argDecl.types[i]);
}
if (methInfo.Name == "llParcelMediaQuery") {
scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaQuery);
}
if (methInfo.Name == "llParcelMediaCommandList") {
scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaCommandList);
}
if (methInfo.IsVirtual) { // call API function
// this should not be needed
// if (methInfo.Name == "llParcelMediaQuery") {
// scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaQuery);
// }
// this should not be needed
// if (methInfo.Name == "llParcelMediaCommandList") {
// scg.ilGen.Emit (errorAt, OpCodes.Call, fixLLParcelMediaCommandList);
// }
if (methInfo.IsVirtual) // call API function
scg.ilGen.Emit (errorAt, OpCodes.Callvirt, methInfo);
} else {
else
scg.ilGen.Emit (errorAt, OpCodes.Call, methInfo);
}
result.Pop (scg, errorAt, retType); // pop result, boxing/unboxing as needed
if (isTaggedCallsCheckRun) {
if (isTaggedCallsCheckRun)
scg.openCallLabel = null;
}
if (doCheckRun) {
if (doCheckRun)
scg.EmitCallCheckRun (errorAt, false); // maybe call CheckRun()
}
}
}
}

View File

@ -99,7 +99,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
new Dictionary<string,FieldInfo> ();
private int m_StackSize;
private int m_HeapSize;
private XMRScriptThread[] m_ScriptThreads;
private int m_WakeUpOne = 0;
public object m_WakeUpLock = new object();
private Dictionary<Thread,XMRScriptThread> m_AllThreads = new Dictionary<Thread,XMRScriptThread> ();
private bool m_SuspendScriptThreadFlag = false;
/**
* @brief Something was just added to the Start or Yield queue so
* wake one of the XMRScriptThread instances to run it.
*/
private Thread m_SleepThread = null;
private bool m_Exiting = false;
@ -165,6 +176,36 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
get { return scriptReferencedAssemblies; }
}
public void WakeUpOne()
{
lock (m_WakeUpLock)
{
m_WakeUpOne++;
Monitor.Pulse(m_WakeUpLock);
}
}
public void AddThread(Thread thd, XMRScriptThread xthd)
{
lock(m_AllThreads)
m_AllThreads.Add(thd, xthd);
}
public void RemoveThread(Thread thd)
{
lock(m_AllThreads)
m_AllThreads.Remove(thd);
}
public XMRScriptThread CurrentScriptThread ()
{
XMRScriptThread st;
lock (m_AllThreads)
m_AllThreads.TryGetValue (Thread.CurrentThread, out st);
return st;
}
public void Initialise(IConfigSource config)
{
TraceCalls("[XMREngine]: Initialize entry");
@ -235,7 +276,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
}
for (int i = 0; i < numThreadScriptWorkers; i ++)
m_ScriptThreads[i] = new XMRScriptThread(this, i);
{
m_ScriptThreads[i] = new XMRScriptThread(this, i);;
}
m_SleepThread = StartMyThread(RunSleepThread, "xmrengine sleep", ThreadPriority.Normal);
@ -678,6 +722,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
XMRScriptThread scriptThread = m_ScriptThreads[i];
if (scriptThread != null)
{
scriptThread.WakeUpScriptThread();
Monitor.PulseAll (m_WakeUpLock);
scriptThread.Terminate();
m_ScriptThreads[i] = null;
}
@ -722,7 +768,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
m_Scene.EventManager.TriggerEmptyScriptCompileQueue (0, "");
m_StartProcessing = true;
for (int i = 0; i < numThreadScriptWorkers; i ++) {
XMRScriptThread.WakeUpOne();
WakeUpOne();
}
m_log.Debug ("[XMREngine]: StartProcessing return");
}
@ -832,15 +878,18 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
case "resume":
m_log.Info ("[XMREngine]: resuming scripts");
m_SuspendScriptThreadFlag = false;
for (int i = 0; i < numThreadScriptWorkers; i ++)
m_ScriptThreads[i].ResumeThread();
m_ScriptThreads[i].WakeUpScriptThread();
Monitor.PulseAll(m_WakeUpLock);
break;
case "suspend":
m_log.Info ("[XMREngine]: suspending scripts");
m_SuspendScriptThreadFlag = true;
for (int i = 0; i < numThreadScriptWorkers; i ++)
m_ScriptThreads[i].SuspendThread();
m_ScriptThreads[i].WakeUpScriptThread();
Monitor.PulseAll(m_WakeUpLock);
break;
case "tracecalls":
@ -1545,7 +1594,14 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state");
m_StartQueue.InsertTail(inst);
}
XMRScriptThread.WakeUpOne();
WakeUpOne();
}
public void QueueToTrunk(ThreadStart thds)
{
lock (m_WakeUpLock)
m_ThunkQueue.Enqueue (thds);
WakeUpOne();
}
/**
@ -1572,7 +1628,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
// Make sure the OS thread is running so it will see the script.
XMRScriptThread.WakeUpOne();
WakeUpOne();
}
/**
@ -1724,7 +1780,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
inst.m_IState = XMRInstState.ONYIELDQ;
m_YieldQueue.InsertTail(inst);
}
XMRScriptThread.WakeUpOne ();
WakeUpOne ();
}
}
@ -1934,12 +1990,113 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
public static void UpdateMyThread ()
{
Watchdog.UpdateThread ();
Watchdog.UpdateThread();
}
public static void MyThreadExiting ()
{
Watchdog.RemoveThread (true);
Watchdog.RemoveThread(true);
}
public void RunScriptThread(XMRScriptThread xthd)
{
XMRInstance inst;
while (!m_Exiting)
{
Watchdog.UpdateThread();
/*
* Handle 'xmr resume/suspend' commands.
*/
if (m_SuspendScriptThreadFlag)
{
lock (m_WakeUpLock)
{
while (m_SuspendScriptThreadFlag &&
!m_Exiting &&
(m_ThunkQueue.Count == 0))
{
Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2);
XMREngine.UpdateMyThread ();
}
}
}
/*
* Maybe there are some scripts waiting to be migrated in or out.
*/
ThreadStart thunk = null;
lock (m_WakeUpLock)
{
if (m_ThunkQueue.Count > 0)
thunk = m_ThunkQueue.Dequeue ();
}
if (thunk != null)
{
inst = (XMRInstance)thunk.Target;
thunk ();
if (m_Exiting || m_SuspendScriptThreadFlag)
continue;
}
if (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.
int numStarts;
for (numStarts = 5; -- numStarts >= 0;)
{
lock (m_StartQueue)
{
inst = m_StartQueue.RemoveHead();
}
if (inst == null) break;
if (inst.m_IState != XMRInstState.ONSTARTQ) throw new Exception("bad state");
xthd.RunInstance (inst);
if (m_Exiting || m_SuspendScriptThreadFlag)
continue;
}
// 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 (m_YieldQueue)
{
inst = m_YieldQueue.RemoveHead();
}
if (inst != null)
{
if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state");
xthd.RunInstance(inst);
numStarts = -1;
}
// If we left something dangling in the m_StartQueue or m_YieldQueue, go back to check it.
if (m_Exiting || numStarts < 0)
continue;
}
// Nothing to do, sleep.
lock (m_WakeUpLock)
{
if (!xthd.m_WakeUpThis && (m_WakeUpOne <= 0) && !m_Exiting)
Monitor.Wait(m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2);
xthd.m_WakeUpThis = false;
if ((m_WakeUpOne > 0) && (--m_WakeUpOne > 0))
Monitor.Pulse (m_WakeUpLock);
}
}
Watchdog.RemoveThread(true);
}
}
}

View File

@ -491,11 +491,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
{
if (this.newStateCode < 0)
{
// Process event given by 'stateCode' and 'eventCode'.
// The event handler should call CheckRun() as often as convenient.
/*
* Process event given by 'stateCode' and 'eventCode'.
* The event handler should call CheckRun() as often as convenient.
*/
int newState = this.stateCode;
seh = this.m_ObjCode.scriptEventHandlerTable[newState,(int)this.eventCode];
if (seh != null)
@ -512,25 +510,19 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
this.ehArgs = null; // we are done with them and no args for
// exit_state()/enter_state() anyway
/*
* The usual case is no state change.
* Even a 'state <samestate>;' statement has no effect except to exit out.
* It does not execute the state_exit() or state_entry() handlers.
* See http://wiki.secondlife.com/wiki/State
*/
// The usual case is no state change.
// Even a 'state <samestate>;' statement has no effect except to exit out.
// It does not execute the state_exit() or state_entry() handlers.
// See http://wiki.secondlife.com/wiki/State
if (newState == this.stateCode)
break;
/*
* Save new state in a more permanent location in case we
* get serialized out while in the state_exit() handler.
*/
// Save new state in a more permanent location in case we
// get serialized out while in the state_exit() handler.
this.newStateCode = newState;
}
/*
* Call old state's state_exit() handler.
*/
// Call old state's state_exit() handler.
this.eventCode = ScriptEventCode.state_exit;
seh = this.m_ObjCode.scriptEventHandlerTable[this.stateCode,(int)ScriptEventCode.state_exit];
if (seh != null)
@ -545,27 +537,19 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
}
}
/*
* Switch over to the new state's state_entry() handler.
*/
// Switch over to the new state's state_entry() handler.
this.stateCode = this.newStateCode;
this.eventCode = ScriptEventCode.state_entry;
this.newStateCode = -1;
/*
* Now that the old state can't possibly start any more activity,
* cancel any listening handlers, etc, of the old state.
*/
// Now that the old state can't possibly start any more activity,
// cancel any listening handlers, etc, of the old state.
this.StateChange ();
/*
* Loop back to execute new state's state_entry() handler.
*/
// Loop back to execute new state's state_entry() handler.
}
/*
* Event no longer being processed.
*/
// Event no longer being processed.
this.eventCode = ScriptEventCode.None;
}
@ -642,6 +626,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
* @brief Convert all LSL_Integers in a list to System.Int32s,
* as required by llParcelMediaQuery().
*/
/*
public static LSL_List FixLLParcelMediaQuery (LSL_List oldlist)
{
object[] oldarray = oldlist.Data;
@ -655,11 +640,12 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
}
return new LSL_List (newarray);
}
*/
/**
* @brief Convert *SOME* LSL_Integers in a list to System.Int32s,
* as required by llParcelMediaCommandList().
*/
/*
public static LSL_List FixLLParcelMediaCommandList (LSL_List oldlist)
{
object[] oldarray = oldlist.Data;
@ -696,7 +682,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
}
return new LSL_List (newarray);
}
*/
public static int xmrHashCode (int i)
{
return i.GetHashCode ();

View File

@ -32,11 +32,6 @@ using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.Api;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.XMREngine;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Scripting;
using OpenSim.Region.Framework.Interfaces;
using log4net;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
@ -88,6 +83,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
* -2: no av granted perms
* -3: av not in region
*/
/* engines should not have own API
public int xmrSeatAvatar (bool owner)
{
// Get avatar to be seated and make sure they have given us ANIMATION permission
@ -118,7 +114,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
presence.HandleAgentRequestSit (null, UUID.Zero, m_host.UUID, OpenMetaverse.Vector3.Zero);
return 0;
}
*/
/**
* @brief llTeleportAgent() is broken in that if you pass it a landmark,
* it still subjects the position to spawn points, as it always
@ -129,6 +125,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
* @param landmark = inventory name or UUID of a landmark object
* @param lookat = looking direction after teleport
*/
/* engines should not have own API
public void xmrTeleportAgent2Landmark (string agent, string landmark, LSL_Vector lookat)
{
// find out about agent to be teleported
@ -172,13 +169,14 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
lookat,
(uint)TeleportFlags.ViaLandmark);
}
*/
/**
* @brief Allow any member of group given by config SetParcelMusicURLGroup to set music URL.
* Code modelled after llSetParcelMusicURL().
* @param newurl = new URL to set (or "" to leave it alone)
* @returns previous URL string
*/
/* engines should not have own API
public string xmrSetParcelMusicURLGroup (string newurl)
{
string groupname = m_ScriptEngine.Config.GetString ("SetParcelMusicURLGroup", "");
@ -200,6 +198,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
if ((newurl != null) && (newurl != "")) land.SetMusicUrl (newurl);
return oldurl;
}
*/
}
public partial class XMRInstance

View File

@ -27,22 +27,10 @@
using System;
using System.Threading;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Remoting.Lifetime;
using System.Security.Policy;
using System.IO;
using System.Xml;
using System.Text;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.Api;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.XMREngine;
using OpenSim.Region.Framework.Scenes;
using log4net;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
@ -78,9 +66,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
*/
public XmlElement GetExecutionState(XmlDocument doc)
{
/*
* When we're detaching an attachment, we need to wait here.
*/
// When we're detaching an attachment, we need to wait here.
// Change this to a 5 second timeout. If things do mess up,
// we don't want to be stuck forever.
@ -92,20 +78,16 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
scriptStateN.SetAttribute("Asset", m_Item.AssetID.ToString());
scriptStateN.SetAttribute ("SourceHash", m_ObjCode.sourceHash);
/*
* Make sure we aren't executing part of the script so it stays
* stable. Setting suspendOnCheckRun tells CheckRun() to suspend
* and return out so RunOne() will release the lock asap.
*/
// Make sure we aren't executing part of the script so it stays
// stable. Setting suspendOnCheckRun tells CheckRun() to suspend
// and return out so RunOne() will release the lock asap.
suspendOnCheckRunHold = true;
lock (m_RunLock)
{
m_RunOnePhase = "GetExecutionState enter";
CheckRunLockInvariants(true);
/*
* Get copy of script globals and stack in relocateable form.
*/
// Get copy of script globals and stack in relocateable form.
MemoryStream snapshotStream = new MemoryStream();
MigrateOutEventHandler(snapshotStream);
Byte[] snapshotBytes = snapshotStream.ToArray();
@ -116,25 +98,19 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
scriptStateN.AppendChild(snapshotN);
m_RunOnePhase = "GetExecutionState B"; CheckRunLockInvariants(true);
/*
* "Running" says whether or not we are accepting new events.
*/
// "Running" says whether or not we are accepting new events.
XmlElement runningN = doc.CreateElement("", "Running", "");
runningN.AppendChild(doc.CreateTextNode(m_Running.ToString()));
scriptStateN.AppendChild(runningN);
m_RunOnePhase = "GetExecutionState C"; CheckRunLockInvariants(true);
/*
* "DoGblInit" says whether or not default:state_entry() will init global vars.
*/
// "DoGblInit" says whether or not default:state_entry() will init global vars.
XmlElement doGblInitN = doc.CreateElement("", "DoGblInit", "");
doGblInitN.AppendChild(doc.CreateTextNode(doGblInit.ToString()));
scriptStateN.AppendChild(doGblInitN);
m_RunOnePhase = "GetExecutionState D"; CheckRunLockInvariants(true);
/*
* More misc data.
*/
// More misc data.
XmlNode permissionsN = doc.CreateElement("", "Permissions", "");
scriptStateN.AppendChild(permissionsN);
@ -147,10 +123,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
permissionsN.Attributes.Append(maskA);
m_RunOnePhase = "GetExecutionState E"; CheckRunLockInvariants(true);
/*
* "DetectParams" are returned by llDetected...() script functions
* for the currently active event, if any.
*/
// "DetectParams" are returned by llDetected...() script functions
// for the currently active event, if any.
if (m_DetectParams != null)
{
XmlElement detParArrayN = doc.CreateElement("", "DetectArray", "");
@ -159,16 +133,14 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
}
m_RunOnePhase = "GetExecutionState F"; CheckRunLockInvariants(true);
/*
* Save any events we have in the queue.
* <EventQueue>
* <Event Name="...">
* <param>...</param> ...
* <DetectParams>...</DetectParams> ...
* </Event>
* ...
* </EventQueue>
*/
// Save any events we have in the queue.
// <EventQueue>
// <Event Name="...">
// <param>...</param> ...
// <DetectParams>...</DetectParams> ...
// </Event>
// ...
// </EventQueue>
XmlElement queuedEventsN = doc.CreateElement("", "EventQueue", "");
lock (m_QueueLock)
{
@ -184,31 +156,24 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
scriptStateN.AppendChild(queuedEventsN);
m_RunOnePhase = "GetExecutionState G"; CheckRunLockInvariants(true);
/*
* "Plugins" indicate enabled timers and listens, etc.
*/
// "Plugins" indicate enabled timers and listens, etc.
Object[] pluginData =
AsyncCommandManager.GetSerializationData(m_Engine,
m_ItemID);
AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID);
XmlNode plugins = doc.CreateElement("", "Plugins", "");
AppendXMLObjectArray(doc, plugins, pluginData, "plugin");
scriptStateN.AppendChild(plugins);
m_RunOnePhase = "GetExecutionState H"; CheckRunLockInvariants(true);
/*
* Let script run again.
*/
// Let script run again.
suspendOnCheckRunHold = false;
m_RunOnePhase = "GetExecutionState leave";
CheckRunLockInvariants(true);
}
/*
* scriptStateN represents the contents of the .state file so
* write the .state file while we are here.
*/
// scriptStateN represents the contents of the .state file so
// write the .state file while we are here.
FileStream fs = File.Create(m_StateFileName);
StreamWriter sw = new StreamWriter(fs);
sw.Write(scriptStateN.OuterXml);
@ -233,32 +198,33 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
// do all the work in the MigrateOutEventHandlerThread() method below
moehstream = stream;
XMRScriptThread cst = XMRScriptThread.CurrentScriptThread ();
if (cst != null) {
XMRScriptThread cst = m_Engine.CurrentScriptThread ();
if (cst != null)
{
// we might be getting called inside some LSL Api function
// so we are already in script thread and thus must do
// migration directly
MigrateOutEventHandlerThread ();
} else {
}
else
{
// some other thread, do migration via a script thread
lock (XMRScriptThread.m_WakeUpLock) {
m_Engine.m_ThunkQueue.Enqueue (this.MigrateOutEventHandlerThread);
}
XMRScriptThread.WakeUpOne ();
m_Engine.QueueToTrunk(this.MigrateOutEventHandlerThread);
// wait for it to complete
lock (moehdone) {
while (moehstream != null) {
lock (moehdone)
{
while (moehstream != null)
Monitor.Wait (moehdone);
}
}
}
// maybe it threw up
if (moehexcep != null) throw moehexcep;
if (moehexcep != null)
throw moehexcep;
}
private Exception moehexcep;
private object moehdone = new object ();
private Stream moehstream;
@ -266,64 +232,65 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
{
Exception except;
try {
/*
* Resume the microthread and it will throw a StackCaptureException()
* with the stack frames saved to this.stackFrames.
* Then write the saved stack frames to the output stream.
*
* There is a stack only if the event code is not None.
*/
if (this.eventCode != ScriptEventCode.None) {
try
{
// Resume the microthread and it will throw a StackCaptureException()
// with the stack frames saved to this.stackFrames.
// Then write the saved stack frames to the output stream.
//
// There is a stack only if the event code is not None.
if (this.eventCode != ScriptEventCode.None)
{
// tell microthread to continue
// it should see captureStackFrames and throw StackCaptureException()
// ...generating XMRStackFrames as it unwinds
this.captureStackFrames = true;
// this.suspendOnCheckRunTemp = true;
except = this.microthread.ResumeEx ();
this.captureStackFrames = false;
if (except == null) {
if (except == null)
throw new Exception ("stack save did not complete");
}
if (!(except is StackCaptureException)) {
if (!(except is StackCaptureException))
throw except;
}
}
/*
* Write script state out, frames and all, to the stream.
* Does not change script state.
*/
// Write script state out, frames and all, to the stream.
// Does not change script state.
moehstream.WriteByte (migrationVersion);
moehstream.WriteByte ((byte)16);
this.MigrateOut (new BinaryWriter (moehstream));
/*
* Now restore script stack.
* Microthread will suspend inside CheckRun() when restore is complete.
*/
if (this.eventCode != ScriptEventCode.None) {
// Now restore script stack.
// Microthread will suspend inside CheckRun() when restore is complete.
if (this.eventCode != ScriptEventCode.None)
{
this.stackFramesRestored = false;
except = this.microthread.StartEx ();
if (except != null) {
throw except;
}
if (!this.stackFramesRestored) {
throw new Exception ("restore after save did not complete");
}
}
} catch (Exception e) {
moehexcep = e;
} finally {
// make sure CheckRunLockInvariants() won't puque
if (this.microthread.Active () == 0) {
this.eventCode = ScriptEventCode.None;
if (except != null)
throw except;
if (!this.stackFramesRestored)
throw new Exception ("restore after save did not complete");
}
}
catch (Exception e)
{
moehexcep = e;
}
finally
{
// make sure CheckRunLockInvariants() won't puque
if (this.microthread.Active () == 0)
this.eventCode = ScriptEventCode.None;
// wake the MigrateOutEventHandler() method above
lock (moehdone) {
lock (moehdone)
{
moehstream = null;
Monitor.Pulse (moehdone);
}

View File

@ -695,7 +695,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
// do all the work in the MigrateInEventHandlerThread() method below
miehstream = stream;
XMRScriptThread cst = XMRScriptThread.CurrentScriptThread ();
XMRScriptThread cst = m_Engine.CurrentScriptThread ();
if (cst != null)
{
// in case we are getting called inside some LSL Api function
@ -704,11 +704,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
else
{
// some other thread, do migration via a script thread
lock (XMRScriptThread.m_WakeUpLock)
{
m_Engine.m_ThunkQueue.Enqueue (this.MigrateInEventHandlerThread);
}
XMRScriptThread.WakeUpOne ();
m_Engine.QueueToTrunk(this.MigrateInEventHandlerThread);
// wait for it to complete
lock (miehdone)
@ -777,79 +773,5 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
}
}
}
/**
* See if permitted by configuration file.
* See OSSL_Api.CheckThreatLevelTest().
*/
public string CheckFetchbinaryAllowed ()
{
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();
switch (curuc)
{
case "ESTATE_MANAGER":
if (m_Engine.m_Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner (ownerID) &&
(m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner != ownerID))
return null;
break;
case "ESTATE_OWNER":
if (m_Engine.m_Scene.RegionInfo.EstateSettings.EstateOwner == ownerID)
return null;
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)
return null;
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":
return null;
default:
UUID 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)
{
string current = id.Trim ();
UUID uuid;
if (UUID.TryParse (current, out uuid))
{
if (uuid != UUID.Zero)
{
if (creatorID == uuid)
return null;
}
}
}
return "fetchbinary not enabled for owner " + ownerID + " creator " + creatorID;
}
}
}

View File

@ -32,7 +32,6 @@ using System.Threading;
namespace OpenSim.Region.ScriptEngine.XMREngine
{
/**
* @brief There are NUMSCRIPTHREADWKRS of these.
* Each sits in a loop checking the Start and Yield queues for
@ -40,35 +39,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
*/
public class XMRScriptThread
{
private static int m_WakeUpOne = 0;
public static object m_WakeUpLock = new object();
private static Dictionary<Thread,XMRScriptThread> m_AllThreads = new Dictionary<Thread,XMRScriptThread> ();
/**
* @brief Something was just added to the Start or Yield queue so
* wake one of the XMRScriptThread instances to run it.
*/
public static void WakeUpOne()
{
lock (m_WakeUpLock)
{
m_WakeUpOne ++;
Monitor.Pulse (m_WakeUpLock);
}
}
public static XMRScriptThread CurrentScriptThread ()
{
XMRScriptThread st;
lock (m_AllThreads) {
m_AllThreads.TryGetValue (Thread.CurrentThread, out st);
}
return st;
}
private bool m_Exiting = false;
private bool m_SuspendScriptThreadFlag = false;
private bool m_WakeUpThis = false;
public bool m_WakeUpThis = false;
public DateTime m_LastRanAt = DateTime.MinValue;
public int m_ScriptThreadTID = 0;
public long m_ScriptExecTime = 0;
@ -80,164 +51,43 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
{
engine = eng;
if(i < 0)
thd = XMREngine.StartMyThread (RunScriptThread, "xmrengine script", ThreadPriority.Normal);
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()
{
m_SuspendScriptThreadFlag = true;
WakeUpScriptThread();
}
public void ResumeThread()
{
m_SuspendScriptThreadFlag = false;
WakeUpScriptThread();
thd = XMREngine.StartMyThread(RunScriptThread, "xmrengineExec" + i.ToString(), ThreadPriority.Normal);
engine.AddThread(thd, this);
m_ScriptThreadTID = thd.ManagedThreadId;
}
public void Terminate()
{
m_Exiting = true;
WakeUpScriptThread();
m_WakeUpThis = true;
if(!thd.Join(250))
thd.Abort();
lock (m_AllThreads)
m_AllThreads.Remove (thd);
engine.RemoveThread(thd);
thd = null;
}
public void TimeSlice()
{
XMRInstance instance = m_RunInstance;
if (instance != null)
instance.suspendOnCheckRunTemp = true;
}
/**
* @brief Wake up this XMRScriptThread instance.
*/
private void WakeUpScriptThread()
public void WakeUpScriptThread()
{
lock (m_WakeUpLock)
{
m_WakeUpThis = true;
Monitor.PulseAll (m_WakeUpLock);
}
}
/**
* @brief Thread that runs the scripts.
*/
private void RunScriptThread()
{
XMRInstance inst;
m_ScriptThreadTID = System.Threading.Thread.CurrentThread.ManagedThreadId;
while (!m_Exiting)
{
XMREngine.UpdateMyThread ();
/*
* Handle 'xmr resume/suspend' commands.
*/
if (m_SuspendScriptThreadFlag)
{
lock (m_WakeUpLock) {
while (m_SuspendScriptThreadFlag &&
!m_Exiting &&
(engine.m_ThunkQueue.Count == 0))
{
Monitor.Wait (m_WakeUpLock, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS / 2);
XMREngine.UpdateMyThread ();
}
}
}
/*
* Maybe there are some scripts waiting to be migrated in or out.
*/
ThreadStart thunk = null;
lock (m_WakeUpLock)
{
if (engine.m_ThunkQueue.Count > 0)
thunk = engine.m_ThunkQueue.Dequeue ();
}
if (thunk != null)
{
inst = (XMRInstance)thunk.Target;
thunk ();
continue;
}
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.
int numStarts;
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");
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)
{
inst = engine.m_YieldQueue.RemoveHead();
}
if (inst != null)
{
if (inst.m_IState != XMRInstState.ONYIELDQ) throw new Exception("bad state");
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;
}
// 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))
Monitor.Pulse (m_WakeUpLock);
}
}
XMREngine.MyThreadExiting ();
}
/**
* @brief A script instance was just removed from the Start or Yield Queue.
* So run it for a little bit then stick in whatever queue it should go in.
*/
private void RunInstance (XMRInstance inst)
private void RunScriptThread()
{
engine.RunScriptThread(this);
}
public void RunInstance (XMRInstance inst)
{
m_LastRanAt = DateTime.UtcNow;
m_ScriptExecTime -= (long)(m_LastRanAt - DateTime.MinValue).TotalMilliseconds;

View File

@ -57,21 +57,28 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
public Exception StartEx ()
{
// We should only be called when no event handler running.
if (active != 0) throw new Exception ("active=" + active);
if (active != 0)
throw new Exception ("active=" + active);
// Start script event handler from very beginning.
active = 1;
Exception except = null;
instance.callMode = XMRInstance.CallMode_NORMAL;
try {
try
{
instance.CallSEH (); // run script event handler
active = 0;
} catch (StackHibernateException) {
if (instance.callMode != XMRInstance.CallMode_SAVE) {
}
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) {
}
catch (Exception e)
{
active = 0;
except = e; // threw exception, save for Start()/Resume()
}
@ -88,21 +95,28 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
public Exception ResumeEx ()
{
// We should only be called when script is hibernating.
if (active >= 0) throw new Exception ("active=" + active);
if (active >= 0)
throw new Exception ("active=" + active);
// Resume script from captured stack.
instance.callMode = XMRInstance.CallMode_RESTORE;
instance.suspendOnCheckRunTemp = true;
Exception except = null;
try {
try
{
instance.CallSEH (); // run script event handler
active = 0;
} catch (StackHibernateException) {
if (instance.callMode != XMRInstance.CallMode_SAVE) {
}
catch (StackHibernateException)
{
if (instance.callMode != XMRInstance.CallMode_SAVE)
{
throw new Exception ("callMode=" + instance.callMode);
}
active = -1;
} catch (Exception e) {
}
catch (Exception e)
{
active = 0;
except = e; // threw exception, save for Start()/Resume()
}