/// <summary> /// Just before returning from method body. /// </summary> /// <remarks>Only method allowed to pop from callstack.</remarks> public override void LeaveMethod() { try { if (callStack.Count == 0) { SafeDebug.Fail("cannot leave empty method"); //should not happen with the fake frame. return; } if (callStack.Count == 1) { this.callMonitor.RunCompleted(); return; //exit from Main, if we did not get Enter(Main). } CallFrame poppedFrame = callStack.First.Value; callStack.RemoveFirst(); this.current = callStack.First.Value; if (poppedFrame.PreemptionsDisabled && !this.current.PreemptionsDisabled) { this.PreemptionEnable(); } if (poppedFrame.Prioritized && !this.current.Prioritized) { MChessChess.UnprioritizePreemptions(); } } catch (Exception e) { LogException(e); } }
public static bool IsBreakingDeadlock() { using (new WrapperSentry()) { return(MChessChess.IsBreakingDeadlock()); } }
public void TaskResume(int ctid) { if (!MChessChess.TaskResume(ctid)) { ChessDetach(); } }
public bool TryExecuteTaskInline(Task task, bool wasQueuedBefore) { int choice = MChessChess.Choose(2); if (choice == 0) { return(false); } else { if (!wasQueuedBefore) { task.Execute(); return(true); } else { bool canceled = TryDequeue(task); if (canceled) { task.Execute(); return(true); } else { // task has already been executed return(false); } } } }
public void TaskSuspend(ChessTask tid) { if (!MChessChess.TaskSuspend(tid)) { ChessDetach(); } }
public static void PreemptionEnable() { using (new WrapperSentry()) { MChessChess.PreemptionEnable(); } }
public void TaskYield() { if (!MChessChess.TaskYield()) { ChessDetach(); } }
public static void Execute(int processCount, Action <OMini.IMiniMPIStringAPI> processWork) { //Console.WriteLine("MiniMPIProgram.Execute {0}", processCount); // disable preemptions in each worker Action <OMini.IMiniMPIStringAPI> processWorkWrap = (x) => { using (new WrapperSentry()){ MChessChess.PreemptionDisable(); } processWork(x); using (new WrapperSentry()){ MChessChess.PreemptionEnable(); } }; // disable preemptions in main using (new WrapperSentry()) { MChessChess.PreemptionDisable(); } OMini.MiniMPIProgram.Execute(processCount, processWorkWrap); using (new WrapperSentry()) { MChessChess.PreemptionEnable(); } }
public Action <T, OTasks.ParallelLoopState> WrapBody(Action <T> body) { return((T t, OTasks.ParallelLoopState ls) => { Exception exception = null; MChessChess.TraceEvent("body(" + t.ToString() + ")"); MChessChess.LeaveChess(); if (OThreading.Thread.CurrentThread == mainthread) { protectingcontext.Dispose(); } try { body(t); } catch (Exception e) // catch recoverable exception in user code { exception = e; } if (OThreading.Thread.CurrentThread == mainthread) { protectingcontext = _ProtectingThreadContext.Acquire(); } MChessChess.EnterChess(); if (exception != null) { global::System.Diagnostics.Debug.Fail("Not implemented: exceptions in Parallel loops"); throw exception; // once we implement this we'll rethrow and let TPL catch & aggregate it } }); }
public static void ObserveCallback(object obj, string name) { using (new WrapperSentry()) { int objnumber = (obj == null) ? 0 : ClrSyncManager.SyncManager.GetSyncVarFromObject(obj); MChessChess.ObserveCallback(objnumber, name); } }
public static void ObserveObjectIdentity(string label, object obj) { using (new WrapperSentry()) { int objnumber = (obj == null) ? 0 : ClrSyncManager.SyncManager.GetSyncVarFromObject(obj); MChessChess.ObservePointerValue(label, objnumber); } }
public int TaskFork() { MChessInt i = new MChessInt(); if (!MChessChess.TaskFork(i)) { ChessDetach(); } return(i.i); }
public override void Shutdown(Exception e) { // finalizers IsInitialized = false; syncVarManager.ReleaseGCAddresses(); this.ExitCode = ChessExitCode.TestFailure; SafeDebug.Assert(this.exitCallback != null, "this.exitCallBack != null"); MChessChess.LeaveChess(); this.exitCallback(ChessExitCode.TestFailure, e); }
private void PreemptionEnable() { if (MyEngine.EnvironmentVars.FlipPreemptSense) { MChessChess.PreemptionDisable(); } else { MChessChess.PreemptionEnable(); } }
public static void PreemptionDisable() { using (new WrapperSentry()) { // need to insert dummy access before turning off preemptions // - otherwise too many schedules get eliminated MChessChess.SyncVarAccess(509, MSyncVarOp.RWVAR_READWRITE); MChessChess.CommitSyncVarAccess(); MChessChess.PreemptionDisable(); } }
public SyncVar GetSyncVarFromUIntPtr(UIntPtr o) { SyncVar ret; if (!uintptr_to_syncvar.TryGetValue(o.ToUInt64(), out ret)) { ret = (SyncVar)MChessChess.GetNextSyncVar(); Conversions.NewVar(ret); uintptr_to_syncvar.Add(o.ToUInt64(), ret); } return(ret); }
private void EndChildThread() { if (manager.BreakDeadlockMode) { MChessChess.WakeNextDeadlockedThread(false, true); } else { childdone = true; manager.ThreadEnd(childthread); } }
public SyncVar GetSyncVarFromGCAddress(GCAddress gca) { SyncVar ret; if (!gca_to_syncvar.TryGetValue(gca, out ret)) { // NOTE: we are ignoring the (highly weird) case where the object might be a Thread ret = (SyncVar)MChessChess.GetNextSyncVar(); Conversions.NewVar(ret); gca.AddRef(); // VERY IMPORTANT: must ref count to keep unmanaged cell alive gca_to_syncvar.Add(gca, ret); } return(ret); }
public void ThreadBegin(Semaphore s) { NumThreads++; s.WaitOne(); if (!MChessChess.TaskBegin()) { ChessDetach(); } OnWakeUp(); if (MyEngine.EnvironmentVars.FlipPreemptSense) { MChessChess.PreemptionDisable(); } }
public SyncVar GetSyncVarFromNativeHandle(System.IntPtr handle) { lock (this) { SyncVar ret; if (handleToSyncVar.TryGetValue(handle, out ret)) { return(ret); } ret = (SyncVar)MChessChess.GetNextSyncVar(); Conversions.NewVar(ret); handleToSyncVar[handle] = ret; return(ret); } }
public void LocalBacktrack() { if (!MChessChess.LocalBacktrack()) { if (MChessChess.IsBreakingDeadlock()) { BreakDeadlockMode = true; throw new Exception("BreakDeadlockException"); } else { ChessDetach(); } } }
public static Action <Object> TaskCreateWrapper(ClrSyncManager manager) { return (delegate(Object o) { try { TaskArg p = (TaskArg)o; p.e.Set(); manager.ThreadBegin(p.s); MChessChess.LeaveChess(); Exception exception = null; try { var tryExecuteTask = p.taskScheduler.GetType().GetMethod("TryExecuteTask", global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance); tryExecuteTask.Invoke(p.taskScheduler, new object[] { p.task }); } catch (Exception e) // catch recoverable exception in user code { exception = e; } MChessChess.EnterChess(); manager.SetMethodInfo("Task.End"); manager.AggregateSyncVarAccess( new object[] { p.task, ((IAsyncResult)p.task).AsyncWaitHandle }, MSyncVarOp.RWEVENT); manager.CommitSyncVarAccess(); if (manager.BreakDeadlockMode) { MChessChess.WakeNextDeadlockedThread(false, true); } else if (exception == null) { manager.ThreadEnd(Original::Thread.CurrentThread); } else { manager.Shutdown(exception); } } catch (Exception e) // catch fatal exception in our code { manager.Shutdown(e); } }); }
public SyncVar GetSyncVarFromObject(object o) { SyncVar ret; WeakReference w = new WeakReference(o); if (o.GetType() == typeof(System.Threading.Thread)) { // in this case, the SyncVar value is the ChessTask id ret = tid_to_ctid[(o as System.Threading.Thread).ManagedThreadId]; return(ret); } else if (!obj_to_syncvar.TryGetValue(w, out ret)) { ret = (SyncVar)MChessChess.GetNextSyncVar(); Conversions.NewVar(ret); obj_to_syncvar.Add(w, ret); } return(ret); }
public void ThreadEnd(int ctid) { if (ctid > 0) { Debug.Assert(ctid == CurrentTid); } if (!MChessChess.TaskEnd()) { if (MChessChess.IsBreakingDeadlock()) { BreakDeadlockMode = true; MChessChess.WakeNextDeadlockedThread(false, false); } else { ChessDetach(); } } }
private void ReportErrorAndExitRaw(string message, ChessExitCode code, bool genRepro, bool fromExitCallback, Exception ex) { DiagnoseInstrumentedUninstrumented(); MErrorInfo errorInfo = ex == null ? null : new MErrorInfo(ex); // It's only safe to write to the results printer if we aren't in the exit callback if (!fromExitCallback) { // TODO: action? This var will always have the value of String.Empty. var action = ""; if (message != "") { MChessChess.ReportError(message, action, errorInfo); } else if (code != 0) { // we have an error code but no message. var newMessage = new ChessResult(code).ToString(); MChessChess.ReportError(newMessage, action, errorInfo); } MChessChess.ReportFinalStatistics((int)code); } if (genRepro) { // must call after all ReportWarning/ReportError calls MChessChess.Done(!fromExitCallback); } else { // Note: The MChessChess.Done already implicitly calls CloseResults, so // we only need to explicitly call it otherwise. MChessChess.CloseResults(); } // Invariant: this should be the only exit in the engine!!! Environment.Exit((int)code); }
public static WaitCallback ThreadCreateWrapper(ClrSyncManager manager) { return (delegate(object o) { try { ThreadRoutineArg p = (ThreadRoutineArg)o; manager.ThreadBegin(p.s); MChessChess.LeaveChess(); Exception exception = null; try { p.wcb(p.o); } catch (Exception e) // catch recoverable exception in user code { exception = e; } MChessChess.EnterChess(); if (manager.BreakDeadlockMode) { MChessChess.WakeNextDeadlockedThread(false, true); } else if (exception == null) { manager.ThreadEnd(Original::Thread.CurrentThread); } else { manager.Shutdown(exception); } } catch (Exception e) // catch fatal exception in our code { manager.Shutdown(e); } }); }
public static Original::ParameterizedThreadStart WrapParamThreadStart(Original::ParameterizedThreadStart del, ClrSyncManager manager) { return(delegate(object o) { try { manager.ThreadBegin(Original::Thread.CurrentThread); MChessChess.LeaveChess(); Exception exception = null; try { CheckThreadReadyForMonitoring(); del(o); } catch (Exception e) // catch recoverable exception in user code { exception = e; } MChessChess.EnterChess(); if (manager.BreakDeadlockMode) { MChessChess.WakeNextDeadlockedThread(false, true); } else if (exception == null) { manager.ThreadEnd(Original::Thread.CurrentThread); } else { manager.Shutdown(exception); } } catch (Exception e) // catch fatal exception in our code { manager.Shutdown(e); } }); }
static internal int ChooseWildcardReceiveToMatch(OMini::MiniMPIStringRuntime self, int[] wildRecvIdxs) { return(Helper.SimpleWrap <int>( delegate(ClrSyncManager manager) { // Don't match unless all our processes are blocked if (!self.AreAllProcessesBlocked()) { return -1; } // let CHESS choose for us return wildRecvIdxs[MChessChess.Choose(wildRecvIdxs.Length)]; }, delegate() { // Don't match unless all our processes are blocked if (!self.AreAllProcessesBlocked()) { return -1; } return self.ChooseWildcardReceiveToMatch(wildRecvIdxs); } )); }
private void DiagnoseInstrumentedUninstrumented() { if (MyEngine.EnvironmentVars.Diagnose) { var uninstrumentedTypes = ThreadExecutionMonitorDispatcher.GetUninstrumentedTypes(); var sortUninstrumented = new SafeOrderedSet <string>(StringComparer.CurrentCulture); foreach (var t in uninstrumentedTypes) { if (t.Value == false) { sortUninstrumented.Add(t.Key.FullName); } } var sortInstrumented = new SafeOrderedSet <string>(StringComparer.CurrentCulture); foreach (var t in uninstrumentedTypes) { if (t.Value == true) { sortInstrumented.Add(t.Key.FullName); } } var diagnose = @"/diagnose output. Uninstrumented types: "; foreach (var s in sortUninstrumented) { diagnose += s + "\n"; } diagnose += "\n/diagnose output. Instrumented types:"; foreach (var s in sortInstrumented) { diagnose += s + "\n"; } MChessChess.ReportWarning(diagnose, "", false); } }
static internal int ChooseSendToMatchWithWildcardReceive(OMini::MiniMPIStringRuntime self, List <int> sendInstrIdxs) { return(Helper.SimpleWrap <int>( delegate(ClrSyncManager manager) { // Don't match unless all our processes are blocked if (!self.AreAllProcessesBlocked()) { return -1; } // let CHESS choose for us return sendInstrIdxs[MChessChess.Choose(sendInstrIdxs.Count)]; }, delegate() { // Don't match unless all our processes are blocked if (!self.AreAllProcessesBlocked()) { return -1; } return self.ChooseSendToMatchWithWildcardReceive(sendInstrIdxs); } )); }