diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs (renamed from OpenSim/Region/ScriptEngine/XMREngine/XMRInstRun.cs) | 504 |
1 files changed, 248 insertions, 256 deletions
diff --git a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstRun.cs b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs index 9654b01..8603fbf 100644 --- a/OpenSim/Region/ScriptEngine/XMREngine/XMRInstRun.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMRInstRun.cs | |||
@@ -32,11 +32,9 @@ using System.Text; | |||
32 | using OpenMetaverse; | 32 | using OpenMetaverse; |
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Region.Framework.Interfaces; | 34 | using OpenSim.Region.Framework.Interfaces; |
35 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
36 | using OpenSim.Region.ScriptEngine.Shared; | 35 | using OpenSim.Region.ScriptEngine.Shared; |
37 | using OpenSim.Region.ScriptEngine.Shared.Api; | 36 | using OpenSim.Region.ScriptEngine.Shared.Api; |
38 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | 37 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
39 | using OpenSim.Region.ScriptEngine.XMREngine; | ||
40 | using OpenSim.Region.Framework.Scenes; | 38 | using OpenSim.Region.Framework.Scenes; |
41 | using log4net; | 39 | using log4net; |
42 | 40 | ||
@@ -48,7 +46,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | |||
48 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | 46 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
49 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | 47 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; |
50 | 48 | ||
51 | namespace OpenSim.Region.ScriptEngine.XMREngine | 49 | namespace OpenSim.Region.ScriptEngine.Yengine |
52 | { | 50 | { |
53 | public partial class XMRInstance | 51 | public partial class XMRInstance |
54 | { | 52 | { |
@@ -65,15 +63,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
65 | */ | 63 | */ |
66 | public void PostEvent(EventParams evt) | 64 | public void PostEvent(EventParams evt) |
67 | { | 65 | { |
68 | ScriptEventCode evc = (ScriptEventCode)Enum.Parse (typeof (ScriptEventCode), | 66 | ScriptEventCode evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), |
69 | evt.EventName); | 67 | evt.EventName); |
70 | 68 | ||
71 | /* | 69 | /* |
72 | * Put event on end of event queue. | 70 | * Put event on end of event queue. |
73 | */ | 71 | */ |
74 | bool startIt = false; | 72 | bool startIt = false; |
75 | bool wakeIt = false; | 73 | bool wakeIt = false; |
76 | lock (m_QueueLock) | 74 | lock(m_QueueLock) |
77 | { | 75 | { |
78 | bool construct = (m_IState == XMRInstState.CONSTRUCT); | 76 | bool construct = (m_IState == XMRInstState.CONSTRUCT); |
79 | 77 | ||
@@ -82,49 +80,50 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
82 | * We can't be state-specific here because state might be different | 80 | * We can't be state-specific here because state might be different |
83 | * by the time this event is dequeued and delivered to the script. | 81 | * by the time this event is dequeued and delivered to the script. |
84 | */ | 82 | */ |
85 | if (!construct && // make sure m_HaveEventHandlers is filled in | 83 | if(!construct && // make sure m_HaveEventHandlers is filled in |
86 | ((uint)evc < (uint)m_HaveEventHandlers.Length) && | 84 | ((uint)evc < (uint)m_HaveEventHandlers.Length) && |
87 | !m_HaveEventHandlers[(int)evc]) { // don't bother if we don't have such a handler in any state | 85 | !m_HaveEventHandlers[(int)evc]) // don't bother if we don't have such a handler in any state |
88 | return; | 86 | return; |
89 | } | 87 | |
90 | 88 | ||
91 | /* | 89 | /* |
92 | * Not running means we ignore any incoming events. | 90 | * Not running means we ignore any incoming events. |
93 | * But queue if still constructing because m_Running is not yet valid. | 91 | * But queue if still constructing because m_Running is not yet valid. |
94 | */ | 92 | */ |
95 | if (!m_Running && !construct) { | 93 | if(!m_Running && !construct) |
96 | return; | 94 | return; |
97 | } | ||
98 | 95 | ||
99 | /* | 96 | /* |
100 | * Only so many of each event type allowed to queue. | 97 | * Only so many of each event type allowed to queue. |
101 | */ | 98 | */ |
102 | if ((uint)evc < (uint)m_EventCounts.Length) { | 99 | if((uint)evc < (uint)m_EventCounts.Length) |
103 | int maxAllowed = MAXEVENTQUEUE; | 100 | { |
104 | if (evc == ScriptEventCode.timer) maxAllowed = 1; | 101 | if(evc == ScriptEventCode.timer) |
105 | if (m_EventCounts[(int)evc] >= maxAllowed) | ||
106 | { | 102 | { |
107 | return; | 103 | if(m_EventCounts[(int)evc] >= 1) |
104 | return; | ||
108 | } | 105 | } |
109 | m_EventCounts[(int)evc] ++; | 106 | else if(m_EventCounts[(int)evc] >= MAXEVENTQUEUE) |
107 | return; | ||
108 | |||
109 | m_EventCounts[(int)evc]++; | ||
110 | } | 110 | } |
111 | 111 | ||
112 | /* | 112 | /* |
113 | * Put event on end of instance's event queue. | 113 | * Put event on end of instance's event queue. |
114 | */ | 114 | */ |
115 | LinkedListNode<EventParams> lln = new LinkedListNode<EventParams>(evt); | 115 | LinkedListNode<EventParams> lln = new LinkedListNode<EventParams>(evt); |
116 | switch (evc) { | 116 | switch(evc) |
117 | 117 | { | |
118 | /* | 118 | /* |
119 | * These need to go first. The only time we manually | 119 | * These need to go first. The only time we manually |
120 | * queue them is for the default state_entry() and we | 120 | * queue them is for the default state_entry() and we |
121 | * need to make sure they go before any attach() events | 121 | * need to make sure they go before any attach() events |
122 | * so the heapLimit value gets properly initialized. | 122 | * so the heapLimit value gets properly initialized. |
123 | */ | 123 | */ |
124 | case ScriptEventCode.state_entry: { | 124 | case ScriptEventCode.state_entry: |
125 | m_EventQueue.AddFirst(lln); | 125 | m_EventQueue.AddFirst(lln); |
126 | break; | 126 | break; |
127 | } | ||
128 | 127 | ||
129 | /* | 128 | /* |
130 | * The attach event sneaks to the front of the queue. | 129 | * The attach event sneaks to the front of the queue. |
@@ -134,22 +133,23 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
134 | * before attach(NULL_KEY) is executed. | 133 | * before attach(NULL_KEY) is executed. |
135 | */ | 134 | */ |
136 | case ScriptEventCode.attach: | 135 | case ScriptEventCode.attach: |
137 | { | 136 | if(evt.Params[0].ToString() == UUID.Zero.ToString()) |
138 | if (evt.Params[0].ToString() == UUID.Zero.ToString()) | ||
139 | { | 137 | { |
140 | LinkedListNode<EventParams> lln2 = null; | 138 | LinkedListNode<EventParams> lln2 = null; |
141 | for (lln2 = m_EventQueue.First; lln2 != null; lln2 = lln2.Next) | 139 | for(lln2 = m_EventQueue.First; lln2 != null; lln2 = lln2.Next) |
142 | { | 140 | { |
143 | EventParams evt2 = lln2.Value; | 141 | EventParams evt2 = lln2.Value; |
144 | ScriptEventCode evc2 = (ScriptEventCode)Enum.Parse (typeof (ScriptEventCode), | 142 | ScriptEventCode evc2 = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), |
145 | evt2.EventName); | 143 | evt2.EventName); |
146 | if ((evc2 != ScriptEventCode.state_entry) && | 144 | if((evc2 != ScriptEventCode.state_entry) && |
147 | (evc2 != ScriptEventCode.attach)) break; | 145 | (evc2 != ScriptEventCode.attach)) |
146 | break; | ||
148 | } | 147 | } |
149 | if (lln2 == null) | 148 | if(lln2 == null) |
150 | m_EventQueue.AddLast(lln); | 149 | m_EventQueue.AddLast(lln); |
151 | else | 150 | else |
152 | m_EventQueue.AddBefore(lln2, lln); | 151 | m_EventQueue.AddBefore(lln2, lln); |
152 | |||
153 | /* If we're detaching, limit the qantum. This will also | 153 | /* If we're detaching, limit the qantum. This will also |
154 | * cause the script to self-suspend after running this | 154 | * cause the script to self-suspend after running this |
155 | * event | 155 | * event |
@@ -160,17 +160,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
160 | } | 160 | } |
161 | else | 161 | else |
162 | m_EventQueue.AddLast(lln); | 162 | m_EventQueue.AddLast(lln); |
163 | |||
163 | break; | 164 | break; |
164 | } | ||
165 | 165 | ||
166 | /* | 166 | /* |
167 | * All others just go on end in the order queued. | 167 | * All others just go on end in the order queued. |
168 | */ | 168 | */ |
169 | default: | 169 | default: |
170 | { | ||
171 | m_EventQueue.AddLast(lln); | 170 | m_EventQueue.AddLast(lln); |
172 | break; | 171 | break; |
173 | } | ||
174 | } | 172 | } |
175 | 173 | ||
176 | /* | 174 | /* |
@@ -180,7 +178,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
180 | * to do the same thing right now. | 178 | * to do the same thing right now. |
181 | * Dont' flag it if it's still suspended! | 179 | * Dont' flag it if it's still suspended! |
182 | */ | 180 | */ |
183 | if ((m_IState == XMRInstState.IDLE) && !m_Suspended) | 181 | if((m_IState == XMRInstState.IDLE) && !m_Suspended) |
184 | { | 182 | { |
185 | m_IState = XMRInstState.ONSTARTQ; | 183 | m_IState = XMRInstState.ONSTARTQ; |
186 | startIt = true; | 184 | startIt = true; |
@@ -190,15 +188,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
190 | * If instance is sleeping (ie, possibly in xmrEventDequeue), | 188 | * If instance is sleeping (ie, possibly in xmrEventDequeue), |
191 | * wake it up if event is in the mask. | 189 | * wake it up if event is in the mask. |
192 | */ | 190 | */ |
193 | if ((m_SleepUntil > DateTime.UtcNow) && !m_Suspended) | 191 | if((m_SleepUntil > DateTime.UtcNow) && !m_Suspended) |
194 | { | 192 | { |
195 | int evc1 = (int)evc; | 193 | int evc1 = (int)evc; |
196 | int evc2 = evc1 - 32; | 194 | int evc2 = evc1 - 32; |
197 | if ((((uint)evc1 < (uint)32) && (((m_SleepEventMask1 >> evc1) & 1) != 0)) || | 195 | if((((uint)evc1 < (uint)32) && (((m_SleepEventMask1 >> evc1) & 1) != 0)) || |
198 | (((uint)evc2 < (uint)32) && (((m_SleepEventMask2 >> evc2) & 1) != 0))) | 196 | (((uint)evc2 < (uint)32) && (((m_SleepEventMask2 >> evc2) & 1) != 0))) |
199 | { | ||
200 | wakeIt = true; | 197 | wakeIt = true; |
201 | } | ||
202 | } | 198 | } |
203 | } | 199 | } |
204 | 200 | ||
@@ -206,13 +202,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
206 | * If transitioned from IDLE->ONSTARTQ, actually go insert it | 202 | * If transitioned from IDLE->ONSTARTQ, actually go insert it |
207 | * on m_StartQueue and give the RunScriptThread() a wake-up. | 203 | * on m_StartQueue and give the RunScriptThread() a wake-up. |
208 | */ | 204 | */ |
209 | if (startIt) | 205 | if(startIt) |
210 | m_Engine.QueueToStart(this); | 206 | m_Engine.QueueToStart(this); |
211 | 207 | ||
212 | /* | 208 | /* |
213 | * Likewise, if the event mask triggered a wake, wake it up. | 209 | * Likewise, if the event mask triggered a wake, wake it up. |
214 | */ | 210 | */ |
215 | if (wakeIt) | 211 | if(wakeIt) |
216 | { | 212 | { |
217 | m_SleepUntil = DateTime.MinValue; | 213 | m_SleepUntil = DateTime.MinValue; |
218 | m_Engine.WakeFromSleep(this); | 214 | m_Engine.WakeFromSleep(this); |
@@ -234,7 +230,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
234 | * up. | 230 | * up. |
235 | */ | 231 | */ |
236 | m_RunOnePhase = "check m_SleepUntil"; | 232 | m_RunOnePhase = "check m_SleepUntil"; |
237 | if (m_SleepUntil > now) | 233 | if(m_SleepUntil > now) |
238 | { | 234 | { |
239 | m_RunOnePhase = "return is sleeping"; | 235 | m_RunOnePhase = "return is sleeping"; |
240 | return XMRInstState.ONSLEEPQ; | 236 | return XMRInstState.ONSLEEPQ; |
@@ -244,7 +240,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
244 | * Also, someone may have called Suspend(). | 240 | * Also, someone may have called Suspend(). |
245 | */ | 241 | */ |
246 | m_RunOnePhase = "check m_SuspendCount"; | 242 | m_RunOnePhase = "check m_SuspendCount"; |
247 | if (m_SuspendCount > 0) | 243 | if(m_SuspendCount > 0) |
248 | { | 244 | { |
249 | m_RunOnePhase = "return is suspended"; | 245 | m_RunOnePhase = "return is suspended"; |
250 | return XMRInstState.SUSPENDED; | 246 | return XMRInstState.SUSPENDED; |
@@ -256,7 +252,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
256 | * back right away, delay a bit so we don't get in infinite loop. | 252 | * back right away, delay a bit so we don't get in infinite loop. |
257 | */ | 253 | */ |
258 | m_RunOnePhase = "lock m_RunLock"; | 254 | m_RunOnePhase = "lock m_RunLock"; |
259 | if (!Monitor.TryEnter (m_RunLock)) | 255 | if(!Monitor.TryEnter(m_RunLock)) |
260 | { | 256 | { |
261 | m_SleepUntil = now.AddMilliseconds(3); | 257 | m_SleepUntil = now.AddMilliseconds(3); |
262 | m_RunOnePhase = "return was locked"; | 258 | m_RunOnePhase = "return was locked"; |
@@ -269,23 +265,22 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
269 | Exception e = null; | 265 | Exception e = null; |
270 | 266 | ||
271 | /* | 267 | /* |
272 | * Maybe we have been disposed. | 268 | * Maybe it has been Disposed() |
273 | */ | 269 | */ |
274 | m_RunOnePhase = "check disposed"; | 270 | if(m_Part == null) |
275 | if (microthread == null) | ||
276 | { | 271 | { |
277 | m_RunOnePhase = "return disposed"; | 272 | m_RunOnePhase = "runone saw it disposed"; |
278 | return XMRInstState.DISPOSED; | 273 | return XMRInstState.DISPOSED; |
279 | } | 274 | } |
280 | 275 | ||
281 | /* | 276 | /* |
282 | * Do some more of the last event if it didn't finish. | 277 | * Do some more of the last event if it didn't finish. |
283 | */ | 278 | */ |
284 | else if (eventCode != ScriptEventCode.None) | 279 | if(this.eventCode != ScriptEventCode.None) |
285 | { | 280 | { |
286 | lock (m_QueueLock) | 281 | lock(m_QueueLock) |
287 | { | 282 | { |
288 | if (m_DetachQuantum > 0 && --m_DetachQuantum == 0) | 283 | if(m_DetachQuantum > 0 && --m_DetachQuantum == 0) |
289 | { | 284 | { |
290 | m_Suspended = true; | 285 | m_Suspended = true; |
291 | m_DetachReady.Set(); | 286 | m_DetachReady.Set(); |
@@ -296,10 +291,10 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
296 | } | 291 | } |
297 | 292 | ||
298 | m_RunOnePhase = "resume old event handler"; | 293 | m_RunOnePhase = "resume old event handler"; |
299 | m_LastRanAt = now; | 294 | m_LastRanAt = now; |
300 | m_InstEHSlice ++; | 295 | m_InstEHSlice++; |
301 | callMode = CallMode_NORMAL; | 296 | callMode = CallMode_NORMAL; |
302 | e = microthread.ResumeEx (); | 297 | e = ResumeEx(); |
303 | } | 298 | } |
304 | 299 | ||
305 | /* | 300 | /* |
@@ -312,7 +307,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
312 | EventParams evt = null; | 307 | EventParams evt = null; |
313 | ScriptEventCode evc = ScriptEventCode.None; | 308 | ScriptEventCode evc = ScriptEventCode.None; |
314 | 309 | ||
315 | lock (m_QueueLock) | 310 | lock(m_QueueLock) |
316 | { | 311 | { |
317 | 312 | ||
318 | /* We can't get here unless the script has been resumed | 313 | /* We can't get here unless the script has been resumed |
@@ -324,7 +319,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
324 | * out and may be improved in the future. | 319 | * out and may be improved in the future. |
325 | */ | 320 | */ |
326 | 321 | ||
327 | if (m_Suspended) | 322 | if(m_Suspended) |
328 | { | 323 | { |
329 | m_RunOnePhase = "m_Suspended is set"; | 324 | m_RunOnePhase = "m_Suspended is set"; |
330 | CheckRunLockInvariants(true); | 325 | CheckRunLockInvariants(true); |
@@ -332,14 +327,14 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
332 | } | 327 | } |
333 | 328 | ||
334 | m_RunOnePhase = "dequeue event"; | 329 | m_RunOnePhase = "dequeue event"; |
335 | if (m_EventQueue.First != null) | 330 | if(m_EventQueue.First != null) |
336 | { | 331 | { |
337 | evt = m_EventQueue.First.Value; | 332 | evt = m_EventQueue.First.Value; |
338 | evc = (ScriptEventCode)Enum.Parse (typeof (ScriptEventCode), | 333 | if(m_DetachQuantum > 0) |
339 | evt.EventName); | ||
340 | if (m_DetachQuantum > 0) | ||
341 | { | 334 | { |
342 | if (evc != ScriptEventCode.attach) | 335 | evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), |
336 | evt.EventName); | ||
337 | if(evc != ScriptEventCode.attach) | ||
343 | { | 338 | { |
344 | /* | 339 | /* |
345 | * This is the case where the attach event | 340 | * This is the case where the attach event |
@@ -355,17 +350,19 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
355 | } | 350 | } |
356 | } | 351 | } |
357 | m_EventQueue.RemoveFirst(); | 352 | m_EventQueue.RemoveFirst(); |
358 | if (evc >= 0) | 353 | evc = (ScriptEventCode)Enum.Parse(typeof(ScriptEventCode), |
359 | m_EventCounts[(int)evc] --; | 354 | evt.EventName); |
355 | if((int)evc >= 0) | ||
356 | m_EventCounts[(int)evc]--; | ||
360 | } | 357 | } |
361 | 358 | ||
362 | /* | 359 | /* |
363 | * If there is no event to dequeue, don't run this script | 360 | * If there is no event to dequeue, don't run this script |
364 | * until another event gets queued. | 361 | * until another event gets queued. |
365 | */ | 362 | */ |
366 | if (evt == null) | 363 | if(evt == null) |
367 | { | 364 | { |
368 | if (m_DetachQuantum > 0) | 365 | if(m_DetachQuantum > 0) |
369 | { | 366 | { |
370 | /* | 367 | /* |
371 | * This will happen if the attach event has run | 368 | * This will happen if the attach event has run |
@@ -385,19 +382,19 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
385 | * Dequeued an event, so start it going until it either | 382 | * Dequeued an event, so start it going until it either |
386 | * finishes or it calls CheckRun(). | 383 | * finishes or it calls CheckRun(). |
387 | */ | 384 | */ |
388 | m_RunOnePhase = "start event handler"; | 385 | m_RunOnePhase = "start event handler"; |
389 | m_DetectParams = evt.DetectParams; | 386 | m_DetectParams = evt.DetectParams; |
390 | m_LastRanAt = now; | 387 | m_LastRanAt = now; |
391 | m_InstEHEvent ++; | 388 | m_InstEHEvent++; |
392 | e = StartEventHandler (evc, evt.Params); | 389 | e = StartEventHandler(evc, evt.Params); |
393 | } | 390 | } |
394 | m_RunOnePhase = "done running"; | 391 | m_RunOnePhase = "done running"; |
395 | m_CPUTime += DateTime.UtcNow.Subtract(now).TotalMilliseconds; | 392 | m_CPUTime += DateTime.UtcNow.Subtract(now).TotalMilliseconds; |
396 | 393 | ||
397 | /* | 394 | /* |
398 | * Maybe it puqued. | 395 | * Maybe it puqued. |
399 | */ | 396 | */ |
400 | if (e != null) | 397 | if(e != null) |
401 | { | 398 | { |
402 | m_RunOnePhase = "handling exception " + e.Message; | 399 | m_RunOnePhase = "handling exception " + e.Message; |
403 | HandleScriptException(e); | 400 | HandleScriptException(e); |
@@ -409,10 +406,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
409 | /* | 406 | /* |
410 | * If event handler completed, get rid of detect params. | 407 | * If event handler completed, get rid of detect params. |
411 | */ | 408 | */ |
412 | if (this.eventCode == ScriptEventCode.None) | 409 | if(this.eventCode == ScriptEventCode.None) |
413 | { | ||
414 | m_DetectParams = null; | 410 | m_DetectParams = null; |
415 | } | 411 | |
416 | } | 412 | } |
417 | finally | 413 | finally |
418 | { | 414 | { |
@@ -432,33 +428,30 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
432 | * @brief Immediately after taking m_RunLock or just before releasing it, check invariants. | 428 | * @brief Immediately after taking m_RunLock or just before releasing it, check invariants. |
433 | */ | 429 | */ |
434 | private ScriptEventCode lastEventCode = ScriptEventCode.None; | 430 | private ScriptEventCode lastEventCode = ScriptEventCode.None; |
435 | private int lastActive = 0; | 431 | private bool lastActive = false; |
436 | private string lastRunPhase = ""; | 432 | private string lastRunPhase = ""; |
437 | 433 | ||
438 | public void CheckRunLockInvariants(bool throwIt) | 434 | public void CheckRunLockInvariants(bool throwIt) |
439 | { | 435 | { |
440 | /* | 436 | /* |
441 | * If not executing any event handler, active should be 0 indicating the microthread stack is not in use. | 437 | * If not executing any event handler, there shouldn't be any saved stack frames. |
442 | * If executing an event handler, active should be -1 indicating stack is in use but suspended. | 438 | * If executing an event handler, there should be some saved stack frames. |
443 | */ | 439 | */ |
444 | IScriptUThread uth = microthread; | 440 | bool active = (stackFrames != null); |
445 | if (uth != null) { | 441 | ScriptEventCode ec = this.eventCode; |
446 | int active = uth.Active (); | 442 | if(((ec == ScriptEventCode.None) && active) || |
447 | ScriptEventCode ec = this.eventCode; | 443 | ((ec != ScriptEventCode.None) && !active)) |
448 | if (((ec == ScriptEventCode.None) && (active != 0)) || | 444 | { |
449 | ((ec != ScriptEventCode.None) && (active >= 0))) { | 445 | Console.WriteLine("CheckRunLockInvariants: script=" + m_DescName); |
450 | Console.WriteLine("CheckRunLockInvariants: script=" + m_DescName); | 446 | Console.WriteLine("CheckRunLockInvariants: eventcode=" + ec.ToString() + ", active=" + active.ToString()); |
451 | Console.WriteLine("CheckRunLockInvariants: eventcode=" + ec.ToString() + ", active=" + active.ToString()); | 447 | Console.WriteLine("CheckRunLockInvariants: m_RunOnePhase=" + m_RunOnePhase); |
452 | Console.WriteLine("CheckRunLockInvariants: m_RunOnePhase=" + m_RunOnePhase); | 448 | Console.WriteLine("CheckRunLockInvariants: lastec=" + lastEventCode + ", lastAct=" + lastActive + ", lastPhase=" + lastRunPhase); |
453 | Console.WriteLine("CheckRunLockInvariants: lastec=" + lastEventCode + ", lastAct=" + lastActive + ", lastPhase=" + lastRunPhase); | 449 | if(throwIt) |
454 | if (throwIt) { | 450 | throw new Exception("CheckRunLockInvariants: eventcode=" + ec.ToString() + ", active=" + active.ToString()); |
455 | throw new Exception("CheckRunLockInvariants: eventcode=" + ec.ToString() + ", active=" + active.ToString()); | ||
456 | } | ||
457 | } | ||
458 | lastEventCode = ec; | ||
459 | lastActive = active; | ||
460 | lastRunPhase = m_RunOnePhase; | ||
461 | } | 451 | } |
452 | lastEventCode = ec; | ||
453 | lastActive = active; | ||
454 | lastRunPhase = m_RunOnePhase; | ||
462 | } | 455 | } |
463 | 456 | ||
464 | /* | 457 | /* |
@@ -475,38 +468,34 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
475 | * from ehArgs[] and will throw an array bounds or cast exception | 468 | * from ehArgs[] and will throw an array bounds or cast exception |
476 | * if it can't. | 469 | * if it can't. |
477 | */ | 470 | */ |
478 | private Exception StartEventHandler (ScriptEventCode eventCode, object[] ehArgs) | 471 | private Exception StartEventHandler(ScriptEventCode eventCode, object[] ehArgs) |
479 | { | 472 | { |
480 | /* | 473 | /* |
481 | * We use this.eventCode == ScriptEventCode.None to indicate we are idle. | 474 | * We use this.eventCode == ScriptEventCode.None to indicate we are idle. |
482 | * So trying to execute ScriptEventCode.None might make a mess. | 475 | * So trying to execute ScriptEventCode.None might make a mess. |
483 | */ | 476 | */ |
484 | if (eventCode == ScriptEventCode.None) | 477 | if(eventCode == ScriptEventCode.None) |
485 | return new Exception ("Can't process ScriptEventCode.None"); | 478 | return new Exception("Can't process ScriptEventCode.None"); |
486 | 479 | ||
487 | /* | 480 | /* |
488 | * Silly to even try if there is no handler defined for this event. | 481 | * Silly to even try if there is no handler defined for this event. |
489 | */ | 482 | */ |
490 | if ((eventCode >= 0) && (m_ObjCode.scriptEventHandlerTable[this.stateCode,(int)eventCode] == null)) | 483 | if(((int)eventCode >= 0) && (m_ObjCode.scriptEventHandlerTable[this.stateCode, (int)eventCode] == null)) |
491 | return null; | 484 | return null; |
492 | 485 | ||
493 | /* | 486 | /* |
494 | * The microthread shouldn't be processing any event code. | 487 | * The microthread shouldn't be processing any event code. |
495 | * These are assert checks so we throw them directly as exceptions. | 488 | * These are assert checks so we throw them directly as exceptions. |
496 | */ | 489 | */ |
497 | if (this.eventCode != ScriptEventCode.None) | 490 | if(this.eventCode != ScriptEventCode.None) |
498 | throw new Exception ("still processing event " + this.eventCode.ToString ()); | 491 | throw new Exception("still processing event " + this.eventCode.ToString()); |
499 | |||
500 | int active = microthread.Active (); | ||
501 | if (active != 0) | ||
502 | throw new Exception ("microthread is active " + active.ToString ()); | ||
503 | 492 | ||
504 | /* | 493 | /* |
505 | * Save eventCode so we know what event handler to run in the microthread. | 494 | * Save eventCode so we know what event handler to run in the microthread. |
506 | * And it also marks us busy so we can't be started again and this event lost. | 495 | * And it also marks us busy so we can't be started again and this event lost. |
507 | */ | 496 | */ |
508 | this.eventCode = eventCode; | 497 | this.eventCode = eventCode; |
509 | this.ehArgs = ehArgs; | 498 | this.ehArgs = ehArgs; |
510 | 499 | ||
511 | /* | 500 | /* |
512 | * This calls ScriptUThread.Main() directly, and returns when Main() [indirectly] | 501 | * This calls ScriptUThread.Main() directly, and returns when Main() [indirectly] |
@@ -515,9 +504,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
515 | * without doing any stack frame restores first. | 504 | * without doing any stack frame restores first. |
516 | */ | 505 | */ |
517 | this.stackFrames = null; | 506 | this.stackFrames = null; |
518 | Exception e; | 507 | return StartEx(); |
519 | e = microthread.StartEx (); | ||
520 | return e; | ||
521 | } | 508 | } |
522 | 509 | ||
523 | 510 | ||
@@ -533,17 +520,17 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
533 | */ | 520 | */ |
534 | eventCode = ScriptEventCode.None; | 521 | eventCode = ScriptEventCode.None; |
535 | 522 | ||
536 | if (e is ScriptDeleteException) | 523 | if(e is ScriptDeleteException) |
537 | { | 524 | { |
538 | /* | 525 | /* |
539 | * Script did something like llRemoveInventory(llGetScriptName()); | 526 | * Script did something like llRemoveInventory(llGetScriptName()); |
540 | * ... to delete itself from the object. | 527 | * ... to delete itself from the object. |
541 | */ | 528 | */ |
542 | m_SleepUntil = DateTime.MaxValue; | 529 | m_SleepUntil = DateTime.MaxValue; |
543 | Verbose ("[XMREngine]: script self-delete {0}", m_ItemID); | 530 | Verbose("[YEngine]: script self-delete {0}", m_ItemID); |
544 | m_Part.Inventory.RemoveInventoryItem(m_ItemID); | 531 | m_Part.Inventory.RemoveInventoryItem(m_ItemID); |
545 | } | 532 | } |
546 | else if (e is ScriptDieException) | 533 | else if(e is ScriptDieException) |
547 | { | 534 | { |
548 | /* | 535 | /* |
549 | * Script did an llDie() | 536 | * Script did an llDie() |
@@ -552,7 +539,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
552 | m_SleepUntil = DateTime.MaxValue; | 539 | m_SleepUntil = DateTime.MaxValue; |
553 | m_Engine.World.DeleteSceneObject(m_Part.ParentGroup, false); | 540 | m_Engine.World.DeleteSceneObject(m_Part.ParentGroup, false); |
554 | } | 541 | } |
555 | else if (e is ScriptResetException) | 542 | else if(e is ScriptResetException) |
556 | { | 543 | { |
557 | /* | 544 | /* |
558 | * Script did an llResetScript(). | 545 | * Script did an llResetScript(). |
@@ -579,63 +566,68 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
579 | { | 566 | { |
580 | StringBuilder msg = new StringBuilder(); | 567 | StringBuilder msg = new StringBuilder(); |
581 | 568 | ||
582 | msg.Append ("[XMREngine]: Exception while running "); | 569 | msg.Append("[YEngine]: Exception while running "); |
583 | msg.Append (m_ItemID); | 570 | msg.Append(m_ItemID); |
584 | msg.Append ('\n'); | 571 | msg.Append('\n'); |
585 | 572 | ||
586 | /* | 573 | /* |
587 | * Add exception message. | 574 | * Add exception message. |
588 | */ | 575 | */ |
589 | string des = e.Message; | 576 | string des = e.Message; |
590 | des = (des == null) ? "" : (": " + des); | 577 | des = (des == null) ? "" : (": " + des); |
591 | msg.Append (e.GetType ().Name + des + "\n"); | 578 | msg.Append(e.GetType().Name + des + "\n"); |
592 | 579 | ||
593 | /* | 580 | /* |
594 | * Tell script owner what to do. | 581 | * Tell script owner what to do. |
595 | */ | 582 | */ |
596 | msg.Append ("Prim: <"); | 583 | msg.Append("Prim: <"); |
597 | msg.Append (m_Part.Name); | 584 | msg.Append(m_Part.Name); |
598 | msg.Append (">, Script: <"); | 585 | msg.Append(">, Script: <"); |
599 | msg.Append (m_Item.Name); | 586 | msg.Append(m_Item.Name); |
600 | msg.Append (">, Location: "); | 587 | msg.Append(">, Location: "); |
601 | msg.Append (m_Engine.World.RegionInfo.RegionName); | 588 | msg.Append(m_Engine.World.RegionInfo.RegionName); |
602 | msg.Append (" <"); | 589 | msg.Append(" <"); |
603 | Vector3 pos = m_Part.AbsolutePosition; | 590 | Vector3 pos = m_Part.AbsolutePosition; |
604 | msg.Append ((int) Math.Floor (pos.X)); | 591 | msg.Append((int)Math.Floor(pos.X)); |
605 | msg.Append (','); | 592 | msg.Append(','); |
606 | msg.Append ((int) Math.Floor (pos.Y)); | 593 | msg.Append((int)Math.Floor(pos.Y)); |
607 | msg.Append (','); | 594 | msg.Append(','); |
608 | msg.Append ((int) Math.Floor (pos.Z)); | 595 | msg.Append((int)Math.Floor(pos.Z)); |
609 | msg.Append (">\nScript must be Reset to re-enable.\n"); | 596 | msg.Append(">\nScript must be Reset to re-enable.\n"); |
610 | 597 | ||
611 | /* | 598 | /* |
612 | * Display full exception message in log. | 599 | * Display full exception message in log. |
613 | */ | 600 | */ |
614 | m_log.Info (msg.ToString() + XMRExceptionStackString (e), e); | 601 | m_log.Info(msg.ToString() + XMRExceptionStackString(e), e); |
615 | 602 | ||
616 | /* | 603 | /* |
617 | * Give script owner the stack dump. | 604 | * Give script owner the stack dump. |
618 | */ | 605 | */ |
619 | msg.Append (XMRExceptionStackString (e)); | 606 | msg.Append(XMRExceptionStackString(e)); |
620 | 607 | ||
621 | /* | 608 | /* |
622 | * Send error message to owner. | 609 | * Send error message to owner. |
623 | * Suppress internal code stack trace lines. | 610 | * Suppress internal code stack trace lines. |
624 | */ | 611 | */ |
625 | string msgst = msg.ToString(); | 612 | string msgst = msg.ToString(); |
626 | if (!msgst.EndsWith ("\n")) msgst += '\n'; | 613 | if(!msgst.EndsWith("\n")) |
614 | msgst += '\n'; | ||
627 | int j = 0; | 615 | int j = 0; |
628 | StringBuilder imstr = new StringBuilder (); | 616 | StringBuilder imstr = new StringBuilder(); |
629 | for (int i = 0; (i = msgst.IndexOf ('\n', i)) >= 0; j = ++ i) { | 617 | for(int i = 0; (i = msgst.IndexOf('\n', i)) >= 0; j = ++i) |
630 | string line = msgst.Substring (j, i - j); | 618 | { |
631 | if (line.StartsWith ("at ")) { | 619 | string line = msgst.Substring(j, i - j); |
632 | if (line.StartsWith ("at (wrapper")) continue; // at (wrapper ... | 620 | if(line.StartsWith("at ")) |
633 | int k = line.LastIndexOf (".cs:"); // ... .cs:linenumber | 621 | { |
634 | if (Int32.TryParse (line.Substring (k + 4), out k)) continue; | 622 | if(line.StartsWith("at (wrapper")) |
623 | continue; // at (wrapper ... | ||
624 | int k = line.LastIndexOf(".cs:"); // ... .cs:linenumber | ||
625 | if(Int32.TryParse(line.Substring(k + 4), out k)) | ||
626 | continue; | ||
635 | } | 627 | } |
636 | this.llOwnerSay (line); | 628 | this.llOwnerSay(line); |
637 | imstr.Append (line); | 629 | imstr.Append(line); |
638 | imstr.Append ('\n'); | 630 | imstr.Append('\n'); |
639 | } | 631 | } |
640 | 632 | ||
641 | /* | 633 | /* |
@@ -643,14 +635,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
643 | * Code modelled from llInstantMessage(). | 635 | * Code modelled from llInstantMessage(). |
644 | */ | 636 | */ |
645 | IMessageTransferModule transferModule = m_Engine.World.RequestModuleInterface<IMessageTransferModule>(); | 637 | IMessageTransferModule transferModule = m_Engine.World.RequestModuleInterface<IMessageTransferModule>(); |
646 | if (transferModule != null) { | 638 | if(transferModule != null) |
639 | { | ||
647 | UUID friendTransactionID = UUID.Random(); | 640 | UUID friendTransactionID = UUID.Random(); |
648 | GridInstantMessage gim = new GridInstantMessage(); | 641 | GridInstantMessage gim = new GridInstantMessage(); |
649 | gim.fromAgentID = new Guid (m_Part.UUID.ToString()); | 642 | gim.fromAgentID = new Guid(m_Part.UUID.ToString()); |
650 | gim.toAgentID = new Guid (m_Part.OwnerID.ToString ()); | 643 | gim.toAgentID = new Guid(m_Part.OwnerID.ToString()); |
651 | gim.imSessionID = new Guid(friendTransactionID.ToString()); | 644 | gim.imSessionID = new Guid(friendTransactionID.ToString()); |
652 | gim.timestamp = (uint)Util.UnixTimeSinceEpoch(); | 645 | gim.timestamp = (uint)Util.UnixTimeSinceEpoch(); |
653 | gim.message = imstr.ToString (); | 646 | gim.message = imstr.ToString(); |
654 | gim.dialog = (byte)19; // messgage from script | 647 | gim.dialog = (byte)19; // messgage from script |
655 | gim.fromGroup = false; | 648 | gim.fromGroup = false; |
656 | gim.offline = (byte)0; | 649 | gim.offline = (byte)0; |
@@ -663,7 +656,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
663 | (int)Math.Floor(pos.X), | 656 | (int)Math.Floor(pos.X), |
664 | (int)Math.Floor(pos.Y), | 657 | (int)Math.Floor(pos.Y), |
665 | (int)Math.Floor(pos.Z)); | 658 | (int)Math.Floor(pos.Z)); |
666 | transferModule.SendInstantMessage(gim, delegate(bool success) {}); | 659 | transferModule.SendInstantMessage(gim, delegate (bool success) |
660 | { | ||
661 | }); | ||
667 | } | 662 | } |
668 | 663 | ||
669 | /* | 664 | /* |
@@ -679,16 +674,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
679 | */ | 674 | */ |
680 | public void Reset() | 675 | public void Reset() |
681 | { | 676 | { |
682 | checkstate: | 677 | checkstate: |
683 | XMRInstState iState = m_IState; | 678 | XMRInstState iState = m_IState; |
684 | switch (iState) { | 679 | switch(iState) |
685 | 680 | { | |
686 | /* | 681 | /* |
687 | * If it's really being constructed now, that's about as reset as we get. | 682 | * If it's really being constructed now, that's about as reset as we get. |
688 | */ | 683 | */ |
689 | case XMRInstState.CONSTRUCT: { | 684 | case XMRInstState.CONSTRUCT: |
690 | return; | 685 | return; |
691 | } | ||
692 | 686 | ||
693 | /* | 687 | /* |
694 | * If it's idle, that means it is ready to receive a new event. | 688 | * If it's idle, that means it is ready to receive a new event. |
@@ -696,15 +690,16 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
696 | * it out of idle, verify that it is still in idle then transition | 690 | * it out of idle, verify that it is still in idle then transition |
697 | * it to resetting so no other thread will touch it. | 691 | * it to resetting so no other thread will touch it. |
698 | */ | 692 | */ |
699 | case XMRInstState.IDLE: { | 693 | case XMRInstState.IDLE: |
700 | lock (m_QueueLock) { | 694 | lock(m_QueueLock) |
701 | if (m_IState == XMRInstState.IDLE) { | 695 | { |
696 | if(m_IState == XMRInstState.IDLE) | ||
697 | { | ||
702 | m_IState = XMRInstState.RESETTING; | 698 | m_IState = XMRInstState.RESETTING; |
703 | break; | 699 | break; |
704 | } | 700 | } |
705 | } | 701 | } |
706 | goto checkstate; | 702 | goto checkstate; |
707 | } | ||
708 | 703 | ||
709 | /* | 704 | /* |
710 | * If it's on the start queue, that means it is about to dequeue an | 705 | * If it's on the start queue, that means it is about to dequeue an |
@@ -712,112 +707,108 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
712 | * can't be started and transition it to resetting so no other thread | 707 | * can't be started and transition it to resetting so no other thread |
713 | * will touch it. | 708 | * will touch it. |
714 | */ | 709 | */ |
715 | case XMRInstState.ONSTARTQ: { | 710 | case XMRInstState.ONSTARTQ: |
716 | lock (m_Engine.m_StartQueue) { | 711 | lock(m_Engine.m_StartQueue) |
717 | if (m_IState == XMRInstState.ONSTARTQ) { | 712 | { |
713 | if(m_IState == XMRInstState.ONSTARTQ) | ||
714 | { | ||
718 | m_Engine.m_StartQueue.Remove(this); | 715 | m_Engine.m_StartQueue.Remove(this); |
719 | m_IState = XMRInstState.RESETTING; | 716 | m_IState = XMRInstState.RESETTING; |
720 | break; | 717 | break; |
721 | } | 718 | } |
722 | } | 719 | } |
723 | goto checkstate; | 720 | goto checkstate; |
724 | } | ||
725 | 721 | ||
726 | /* | 722 | /* |
727 | * If it's running, tell CheckRun() to suspend the thread then go back | 723 | * If it's running, tell CheckRun() to suspend the thread then go back |
728 | * to see what it got transitioned to. | 724 | * to see what it got transitioned to. |
729 | */ | 725 | */ |
730 | case XMRInstState.RUNNING: { | 726 | case XMRInstState.RUNNING: |
731 | suspendOnCheckRunHold = true; | 727 | suspendOnCheckRunHold = true; |
732 | lock (m_QueueLock) { } | 728 | lock(m_QueueLock) |
729 | { | ||
730 | } | ||
733 | goto checkstate; | 731 | goto checkstate; |
734 | } | 732 | |
735 | 733 | ||
736 | /* | 734 | /* |
737 | * If it's sleeping, remove it from sleep queue and transition it to | 735 | * If it's sleeping, remove it from sleep queue and transition it to |
738 | * resetting so no other thread will touch it. | 736 | * resetting so no other thread will touch it. |
739 | */ | 737 | */ |
740 | case XMRInstState.ONSLEEPQ: { | 738 | case XMRInstState.ONSLEEPQ: |
741 | lock (m_Engine.m_SleepQueue) { | 739 | lock(m_Engine.m_SleepQueue) |
742 | if (m_IState == XMRInstState.ONSLEEPQ) { | 740 | { |
741 | if(m_IState == XMRInstState.ONSLEEPQ) | ||
742 | { | ||
743 | m_Engine.m_SleepQueue.Remove(this); | 743 | m_Engine.m_SleepQueue.Remove(this); |
744 | m_IState = XMRInstState.RESETTING; | 744 | m_IState = XMRInstState.RESETTING; |
745 | break; | 745 | break; |
746 | } | 746 | } |
747 | } | 747 | } |
748 | goto checkstate; | 748 | goto checkstate; |
749 | } | ||
750 | 749 | ||
751 | /* | 750 | /* |
752 | * It was just removed from the sleep queue and is about to be put | 751 | * It was just removed from the sleep queue and is about to be put |
753 | * on the yield queue (ie, is being woken up). | 752 | * on the yield queue (ie, is being woken up). |
754 | * Let that thread complete transition and try again. | 753 | * Let that thread complete transition and try again. |
755 | */ | 754 | */ |
756 | case XMRInstState.REMDFROMSLPQ: { | 755 | case XMRInstState.REMDFROMSLPQ: |
757 | Sleep (10); | 756 | Sleep(10); |
758 | goto checkstate; | 757 | goto checkstate; |
759 | } | ||
760 | 758 | ||
761 | /* | 759 | /* |
762 | * If it's yielding, remove it from yield queue and transition it to | 760 | * If it's yielding, remove it from yield queue and transition it to |
763 | * resetting so no other thread will touch it. | 761 | * resetting so no other thread will touch it. |
764 | */ | 762 | */ |
765 | case XMRInstState.ONYIELDQ: { | 763 | case XMRInstState.ONYIELDQ: |
766 | lock (m_Engine.m_YieldQueue) { | 764 | lock(m_Engine.m_YieldQueue) |
767 | if (m_IState == XMRInstState.ONYIELDQ) { | 765 | { |
766 | if(m_IState == XMRInstState.ONYIELDQ) | ||
767 | { | ||
768 | m_Engine.m_YieldQueue.Remove(this); | 768 | m_Engine.m_YieldQueue.Remove(this); |
769 | m_IState = XMRInstState.RESETTING; | 769 | m_IState = XMRInstState.RESETTING; |
770 | break; | 770 | break; |
771 | } | 771 | } |
772 | } | 772 | } |
773 | goto checkstate; | 773 | goto checkstate; |
774 | } | ||
775 | 774 | ||
776 | /* | 775 | /* |
777 | * If it just finished running something, let that thread transition it | 776 | * If it just finished running something, let that thread transition it |
778 | * to its next state then check again. | 777 | * to its next state then check again. |
779 | */ | 778 | */ |
780 | case XMRInstState.FINISHED: { | 779 | case XMRInstState.FINISHED: |
781 | Sleep (10); | 780 | Sleep(10); |
782 | goto checkstate; | 781 | goto checkstate; |
783 | } | ||
784 | 782 | ||
785 | /* | 783 | /* |
786 | * If it's disposed, that's about as reset as it gets. | 784 | * If it's disposed, that's about as reset as it gets. |
787 | */ | 785 | */ |
788 | case XMRInstState.DISPOSED: { | 786 | case XMRInstState.DISPOSED: |
789 | return; | 787 | return; |
790 | } | ||
791 | 788 | ||
792 | /* | 789 | /* |
793 | * Some other thread is already resetting it, let it finish. | 790 | * Some other thread is already resetting it, let it finish. |
794 | */ | 791 | */ |
795 | case XMRInstState.RESETTING: { | 792 | case XMRInstState.RESETTING: |
796 | return; | 793 | return; |
797 | } | ||
798 | 794 | ||
799 | default: throw new Exception("bad state"); | 795 | |
796 | default: | ||
797 | throw new Exception("bad state"); | ||
800 | } | 798 | } |
801 | 799 | ||
802 | /* | 800 | /* |
803 | * This thread transitioned the instance to RESETTING so reset it. | 801 | * This thread transitioned the instance to RESETTING so reset it. |
804 | */ | 802 | */ |
805 | lock (m_RunLock) { | 803 | lock(m_RunLock) |
804 | { | ||
806 | CheckRunLockInvariants(true); | 805 | CheckRunLockInvariants(true); |
807 | 806 | ||
808 | /* | 807 | /* |
809 | * No other thread should have transitioned it from RESETTING. | 808 | * No other thread should have transitioned it from RESETTING. |
810 | */ | 809 | */ |
811 | if (m_IState != XMRInstState.RESETTING) throw new Exception("bad state"); | 810 | if(m_IState != XMRInstState.RESETTING) |
812 | 811 | throw new Exception("bad state"); | |
813 | /* | ||
814 | * If the microthread is active, that means it has call frame | ||
815 | * context that we don't want. Throw it out and get a fresh one. | ||
816 | */ | ||
817 | if (microthread.Active () < 0) { | ||
818 | microthread.Dispose (); | ||
819 | microthread = (IScriptUThread)m_Engine.uThreadCtor.Invoke (new object[] { this }); | ||
820 | } | ||
821 | 812 | ||
822 | /* | 813 | /* |
823 | * Mark it idle now so it can get queued to process new stuff. | 814 | * Mark it idle now so it can get queued to process new stuff. |
@@ -836,21 +827,22 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
836 | 827 | ||
837 | private void ClearQueueExceptLinkMessages() | 828 | private void ClearQueueExceptLinkMessages() |
838 | { | 829 | { |
839 | lock (m_QueueLock) { | 830 | lock(m_QueueLock) |
831 | { | ||
840 | EventParams[] linkMessages = new EventParams[m_EventQueue.Count]; | 832 | EventParams[] linkMessages = new EventParams[m_EventQueue.Count]; |
841 | int n = 0; | 833 | int n = 0; |
842 | foreach (EventParams evt2 in m_EventQueue) { | 834 | foreach(EventParams evt2 in m_EventQueue) |
843 | if (evt2.EventName == "link_message") { | 835 | { |
836 | if(evt2.EventName == "link_message") | ||
844 | linkMessages[n++] = evt2; | 837 | linkMessages[n++] = evt2; |
845 | } | ||
846 | } | 838 | } |
847 | 839 | ||
848 | m_EventQueue.Clear(); | 840 | m_EventQueue.Clear(); |
849 | for (int i = m_EventCounts.Length; -- i >= 0;) m_EventCounts[i] = 0; | 841 | for(int i = m_EventCounts.Length; --i >= 0;) |
842 | m_EventCounts[i] = 0; | ||
850 | 843 | ||
851 | for (int i = 0; i < n; i ++) { | 844 | for(int i = 0; i < n; i++) |
852 | m_EventQueue.AddLast(linkMessages[i]); | 845 | m_EventQueue.AddLast(linkMessages[i]); |
853 | } | ||
854 | 846 | ||
855 | m_EventCounts[(int)ScriptEventCode.link_message] = n; | 847 | m_EventCounts[(int)ScriptEventCode.link_message] = n; |
856 | } | 848 | } |
@@ -858,10 +850,11 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
858 | 850 | ||
859 | private void ClearQueue() | 851 | private void ClearQueue() |
860 | { | 852 | { |
861 | lock (m_QueueLock) | 853 | lock(m_QueueLock) |
862 | { | 854 | { |
863 | m_EventQueue.Clear(); // no events queued | 855 | m_EventQueue.Clear(); // no events queued |
864 | for (int i = m_EventCounts.Length; -- i >= 0;) m_EventCounts[i] = 0; | 856 | for(int i = m_EventCounts.Length; --i >= 0;) |
857 | m_EventCounts[i] = 0; | ||
865 | } | 858 | } |
866 | } | 859 | } |
867 | 860 | ||
@@ -882,7 +875,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
882 | m_Part.Inventory.GetInventoryItem(m_ItemID).PermsMask = 0; | 875 | m_Part.Inventory.GetInventoryItem(m_ItemID).PermsMask = 0; |
883 | m_Part.Inventory.GetInventoryItem(m_ItemID).PermsGranter = UUID.Zero; | 876 | m_Part.Inventory.GetInventoryItem(m_ItemID).PermsGranter = UUID.Zero; |
884 | IUrlModule urlModule = m_Engine.World.RequestModuleInterface<IUrlModule>(); | 877 | IUrlModule urlModule = m_Engine.World.RequestModuleInterface<IUrlModule>(); |
885 | if (urlModule != null) | 878 | if(urlModule != null) |
886 | urlModule.ScriptRemoved(m_ItemID); | 879 | urlModule.ScriptRemoved(m_ItemID); |
887 | 880 | ||
888 | AsyncCommandManager.RemoveScript(m_Engine, m_LocalID, m_ItemID); | 881 | AsyncCommandManager.RemoveScript(m_Engine, m_LocalID, m_ItemID); |
@@ -890,8 +883,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
890 | m_RunOnePhase = "ResetLocked: clearing current event"; | 883 | m_RunOnePhase = "ResetLocked: clearing current event"; |
891 | this.eventCode = ScriptEventCode.None; // not processing an event | 884 | this.eventCode = ScriptEventCode.None; // not processing an event |
892 | m_DetectParams = null; // not processing an event | 885 | m_DetectParams = null; // not processing an event |
893 | m_SleepUntil = DateTime.MinValue; // not doing llSleep() | 886 | m_SleepUntil = DateTime.MinValue; // not doing llSleep() |
894 | m_ResetCount ++; // has been reset once more | 887 | m_ResetCount++; // has been reset once more |
895 | 888 | ||
896 | /* | 889 | /* |
897 | * Tell next call to 'default state_entry()' to reset all global | 890 | * Tell next call to 'default state_entry()' to reset all global |
@@ -906,8 +899,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
906 | m_RunOnePhase = "ResetLocked: posting default:state_entry() event"; | 899 | m_RunOnePhase = "ResetLocked: posting default:state_entry() event"; |
907 | stateCode = 0; | 900 | stateCode = 0; |
908 | m_Part.SetScriptEvents(m_ItemID, GetStateEventFlags(0)); | 901 | m_Part.SetScriptEvents(m_ItemID, GetStateEventFlags(0)); |
909 | PostEvent(new EventParams("state_entry", | 902 | PostEvent(new EventParams("state_entry", |
910 | zeroObjectArray, | 903 | zeroObjectArray, |
911 | zeroDetectParams)); | 904 | zeroDetectParams)); |
912 | 905 | ||
913 | /* | 906 | /* |
@@ -920,27 +913,30 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
920 | 913 | ||
921 | private void ReleaseControls() | 914 | private void ReleaseControls() |
922 | { | 915 | { |
923 | if (m_Part != null) | 916 | if(m_Part != null) |
924 | { | 917 | { |
925 | bool found; | 918 | bool found; |
926 | int permsMask; | 919 | int permsMask; |
927 | UUID permsGranter; | 920 | UUID permsGranter; |
928 | 921 | ||
929 | try { | 922 | try |
923 | { | ||
930 | permsGranter = m_Part.TaskInventory[m_ItemID].PermsGranter; | 924 | permsGranter = m_Part.TaskInventory[m_ItemID].PermsGranter; |
931 | permsMask = m_Part.TaskInventory[m_ItemID].PermsMask; | 925 | permsMask = m_Part.TaskInventory[m_ItemID].PermsMask; |
932 | found = true; | 926 | found = true; |
933 | } catch { | 927 | } |
928 | catch | ||
929 | { | ||
934 | permsGranter = UUID.Zero; | 930 | permsGranter = UUID.Zero; |
935 | permsMask = 0; | 931 | permsMask = 0; |
936 | found = false; | 932 | found = false; |
937 | } | 933 | } |
938 | 934 | ||
939 | if (found && ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)) { | 935 | if(found && ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)) |
936 | { | ||
940 | ScenePresence presence = m_Engine.World.GetScenePresence(permsGranter); | 937 | ScenePresence presence = m_Engine.World.GetScenePresence(permsGranter); |
941 | if (presence != null) { | 938 | if(presence != null) |
942 | presence.UnRegisterControlEventsToScript(m_LocalID, m_ItemID); | 939 | presence.UnRegisterControlEventsToScript(m_LocalID, m_ItemID); |
943 | } | ||
944 | } | 940 | } |
945 | } | 941 | } |
946 | } | 942 | } |
@@ -949,61 +945,53 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
949 | * @brief The script code should call this routine whenever it is | 945 | * @brief The script code should call this routine whenever it is |
950 | * convenient to perform a migation or switch microthreads. | 946 | * convenient to perform a migation or switch microthreads. |
951 | */ | 947 | */ |
952 | public override void CheckRunWork () | 948 | public override void CheckRunWork() |
953 | { | 949 | { |
954 | if(!suspendOnCheckRunHold && ! suspendOnCheckRunTemp) | 950 | if(!suspendOnCheckRunHold && !suspendOnCheckRunTemp) |
955 | { | 951 | { |
956 | if(Util.GetTimeStampMS() - m_SliceStart < 60.0) | 952 | if(Util.GetTimeStampMS() - m_SliceStart < 60.0) |
957 | return; | 953 | return; |
958 | suspendOnCheckRunTemp = true; | 954 | suspendOnCheckRunTemp = true; |
959 | } | 955 | } |
960 | |||
961 | m_CheckRunPhase = "entered"; | 956 | m_CheckRunPhase = "entered"; |
962 | 957 | ||
963 | /* | 958 | /* |
964 | * Stay stuck in this loop as long as something wants us suspended. | 959 | * Stay stuck in this loop as long as something wants us suspended. |
965 | */ | 960 | */ |
966 | while (suspendOnCheckRunHold || suspendOnCheckRunTemp) | 961 | while(suspendOnCheckRunHold || suspendOnCheckRunTemp) |
967 | { | 962 | { |
968 | m_CheckRunPhase = "top of while"; | 963 | m_CheckRunPhase = "top of while"; |
964 | suspendOnCheckRunTemp = false; | ||
969 | 965 | ||
970 | /* | 966 | switch(this.callMode) |
971 | * See if MigrateOutEventHandler() has been called. | ||
972 | * If so, dump our stack to stackFrames and unwind. | ||
973 | */ | ||
974 | if (this.captureStackFrames) | ||
975 | { | 967 | { |
968 | // Now we are ready to suspend the microthread. | ||
969 | // This is like a longjmp() to the most recent StartEx() or ResumeEx() | ||
970 | // with a simultaneous setjmp() so ResumeEx() can longjmp() back here. | ||
971 | |||
972 | // the script event handler wants to hibernate | ||
973 | // capture stack frames and unwind to Start() or Resume() | ||
974 | case CallMode_NORMAL: | ||
975 | m_CheckRunPhase = "suspending"; | ||
976 | callMode = XMRInstance.CallMode_SAVE; | ||
977 | stackFrames = null; | ||
978 | throw new StackHibernateException(); | ||
979 | |||
980 | // We get here when the script state has been read in by MigrateInEventHandler(). | ||
981 | // Since the stack is completely restored at this point, any subsequent calls | ||
982 | // within the functions should do their normal processing instead of trying to | ||
983 | // restore their state. | ||
984 | |||
985 | // the stack has been restored as a result of calling ResumeEx() | ||
986 | // tell script code to process calls normally | ||
987 | case CallMode_RESTORE: | ||
988 | this.callMode = CallMode_NORMAL; | ||
989 | break; | ||
976 | 990 | ||
977 | /* | 991 | default: |
978 | * Puque our stack to the output stream. | 992 | throw new Exception("callMode=" + callMode); |
979 | * But otherwise, our state remains intact. | ||
980 | */ | ||
981 | m_CheckRunPhase = "saving"; | ||
982 | this.callMode = CallMode_SAVE; | ||
983 | this.stackFrames = null; | ||
984 | throw new StackCaptureException (); | ||
985 | } | ||
986 | |||
987 | /* | ||
988 | * We get here when the script state has been read in by MigrateInEventHandler(). | ||
989 | * Since the stack is completely restored at this point, any subsequent calls | ||
990 | * within the functions should do their normal processing instead of trying to | ||
991 | * restore their state. | ||
992 | */ | ||
993 | if (this.callMode == CallMode_RESTORE) | ||
994 | { | ||
995 | stackFramesRestored = true; | ||
996 | this.callMode = CallMode_NORMAL; | ||
997 | } | 993 | } |
998 | 994 | ||
999 | /* | ||
1000 | * Now we are ready to suspend the microthread. | ||
1001 | * This is like a longjmp() to the most recent StartEx() or ResumeEx() | ||
1002 | * with a simultaneous setjmp() so ResumeEx() can longjmp() back here. | ||
1003 | */ | ||
1004 | m_CheckRunPhase = "suspending"; | ||
1005 | suspendOnCheckRunTemp = false; | ||
1006 | microthread.Hiber (); | ||
1007 | m_CheckRunPhase = "resumed"; | 995 | m_CheckRunPhase = "resumed"; |
1008 | } | 996 | } |
1009 | 997 | ||
@@ -1013,7 +1001,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1013 | * Upon return from CheckRun() it should always be the case that the script is | 1001 | * Upon return from CheckRun() it should always be the case that the script is |
1014 | * going to process calls normally, neither saving nor restoring stack frame state. | 1002 | * going to process calls normally, neither saving nor restoring stack frame state. |
1015 | */ | 1003 | */ |
1016 | if (callMode != CallMode_NORMAL) throw new Exception ("bad callMode " + callMode); | 1004 | if(callMode != CallMode_NORMAL) |
1005 | throw new Exception("bad callMode " + callMode); | ||
1017 | } | 1006 | } |
1018 | 1007 | ||
1019 | /** | 1008 | /** |
@@ -1021,12 +1010,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1021 | */ | 1010 | */ |
1022 | public void ResumeIt() | 1011 | public void ResumeIt() |
1023 | { | 1012 | { |
1024 | lock (m_QueueLock) | 1013 | lock(m_QueueLock) |
1025 | { | 1014 | { |
1026 | m_Suspended = false; | 1015 | m_Suspended = false; |
1027 | if ((m_EventQueue != null) && | 1016 | if((m_EventQueue != null) && |
1028 | (m_EventQueue.First != null) && | 1017 | (m_EventQueue.First != null) && |
1029 | (m_IState == XMRInstState.IDLE)) { | 1018 | (m_IState == XMRInstState.IDLE)) |
1019 | { | ||
1030 | m_IState = XMRInstState.ONSTARTQ; | 1020 | m_IState = XMRInstState.ONSTARTQ; |
1031 | m_Engine.QueueToStart(this); | 1021 | m_Engine.QueueToStart(this); |
1032 | } | 1022 | } |
@@ -1039,7 +1029,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1039 | */ | 1029 | */ |
1040 | public void SuspendIt() | 1030 | public void SuspendIt() |
1041 | { | 1031 | { |
1042 | lock (m_QueueLock) | 1032 | lock(m_QueueLock) |
1043 | { | 1033 | { |
1044 | m_Suspended = true; | 1034 | m_Suspended = true; |
1045 | } | 1035 | } |
@@ -1052,5 +1042,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine | |||
1052 | * to intercept this exception as it would block the stack capture | 1042 | * to intercept this exception as it would block the stack capture |
1053 | * functionality. | 1043 | * functionality. |
1054 | */ | 1044 | */ |
1055 | public class StackCaptureException : Exception, IXMRUncatchable { } | 1045 | public class StackCaptureException: Exception, IXMRUncatchable |
1046 | { | ||
1047 | } | ||
1056 | } | 1048 | } |