public static T SimpleRefWrap <T>(ref T tgt, SimpleRefDel <T> originalCode, String instrMethod) { using (_ProtectingThreadContext.Acquire()) { if (WrapperSentry.Wrap()) { ClrSyncManager manager = ClrSyncManager.SyncManager; manager.SetMethodInfo(instrMethod); if (manager.TrackGC) { return(ref_wrap_gcaddr(manager, ref tgt, originalCode)); } else if (manager.TrackVolatile) { return(ref_wrap_uintptr(manager, ref tgt, originalCode)); } else { return(originalCode(ref tgt)); } } else { return(originalCode(ref tgt)); } } }
public static Timer CreateTimer(ClrSyncManager manager, Original::TimerCallback timerCallback, object state, TimeSpan dueTime, TimeSpan period) { TimerRoutineArg argument = new TimerRoutineArg(); argument.callback = timerCallback; argument.state = state; argument.dueTime = dueTime; argument.Period = period; argument.selfSemaphore = new Semaphore(0, 1); argument.parentSemaphore = new Semaphore(0, 1); argument.disposed = false; argument.changed = true; Timer ret = new Timer(TimerCreateWrapper, argument, 0, Timeout.Infinite); argument.timer = ret; timer2tra.Add(ret, argument); int child = manager.TaskFork(); argument.parentSemaphore.WaitOne(); manager.RegisterTaskSemaphore(child, argument.selfSemaphore, false); manager.TaskResume(child); return(ret); }
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 static void SimpleWrap <T>(ref T r, SimpleDelManagerRef <T> instrumentedCode, SimpleDelRef <T> originalCode) { using (_ProtectingThreadContext.Acquire()) { if (WrapperSentry.Wrap()) { using (new WrapperSentry()) { ClrSyncManager manager = ClrSyncManager.SyncManager; instrumentedCode(manager, ref r); } } else { originalCode(ref r); } } }
public static T SimpleWrap <T>(SimpleDelManager <T> instrumentedCode, SimpleDel <T> originalCode) { using (_ProtectingThreadContext.Acquire()) { if (WrapperSentry.Wrap()) { using (new WrapperSentry()) { ClrSyncManager manager = ClrSyncManager.SyncManager; return(instrumentedCode(manager)); } } else { return(originalCode()); } } }
private static T ref_wrap_uintptr <T>(ClrSyncManager manager, ref T tgt, SimpleRefDel <T> originalCode) { T ret; var ptr = ObjectTracking.GetCurrentRawAddress(ref tgt); manager.SyncVarAccess(ptr, MSyncVarOp.RWVAR_READWRITE); try { ret = originalCode(ref tgt); } catch (Exception e) { manager.CommitSyncVarAccess(); throw e; } manager.CommitSyncVarAccess(); return(ret); }
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 T SimpleContextExposingWrap <T>(SimpleDelManagerContext <T> instrumentedCode, SimpleDel <T> originalCode) { IDisposable protectingcontext = _ProtectingThreadContext.Acquire(); try { if (WrapperSentry.Wrap()) { using (new WrapperSentry()) { ClrSyncManager manager = ClrSyncManager.SyncManager; return(instrumentedCode(manager, ref protectingcontext)); } } else { return(originalCode()); } } finally { protectingcontext.Dispose(); } }
private static T ref_wrap_gcaddr <T>(ClrSyncManager manager, ref T tgt, SimpleRefDel <T> originalCode) { GCAddress gca; if (GCAddress.FromByRef(ref tgt, out gca)) { try { manager.SyncVarAccess(gca, MSyncVarOp.RWVAR_READWRITE); T ret; try { ret = originalCode(ref tgt); } catch (Exception e) { manager.CommitSyncVarAccess(); throw e; } manager.CommitSyncVarAccess(); return(ret); } finally { gca.Release(); } } else { // GC tracking returns false when addr is // - On the stack, or // - Allocated by native code, or // - When it points to certain static fields, and you have only volatile-tracking enabled, but not all read/write accesses. return(ref_wrap_uintptr <T>(manager, ref tgt, originalCode)); } }
public static WaitOrTimerCallback RegisterWaitForSingleObjectWrapper(ClrSyncManager manager) { return (delegate(object argument, bool timedOut) { try { global::System.Diagnostics.Debug.Assert(!timedOut); Helper.WaitOrTimerCallbackRoutineArg p = (Helper.WaitOrTimerCallbackRoutineArg)argument; p.a.Set(); manager.ThreadBegin(p.s); WaitHandle cancelObject = null; while (true) { manager.SetMethodInfo("RegisteredWaitForSingleObject.CheckCancellation"); manager.SyncVarAccess(p, MSyncVarOp.RWVAR_READWRITE); bool cancelled = p.canceled; cancelObject = p.onCancellation; if (cancelled) { p.finished = true; } manager.CommitSyncVarAccess(); if (cancelled) { break; } MChessChess.LeaveChess(); bool flag = __Substitutions.System.Threading.WaitHandle.WaitOne(p.waitObject, (int)p.millisecondsTimeOutInterval, false); p.callback(p.state, !flag); MChessChess.EnterChess(); if (p.executeOnlyOnce) { manager.SetMethodInfo("RegisteredWaitForSingleObject.ReadOnCancellation"); manager.SyncVarAccess(p, MSyncVarOp.RWVAR_READWRITE); cancelObject = p.onCancellation; p.finished = true; manager.CommitSyncVarAccess(); break; } } MChessChess.LeaveChess(); Exception exception = null; try { if (cancelObject != null) { __Substitutions.System.Threading.EventWaitHandle.Set((EventWaitHandle)cancelObject); } } catch (Exception e) // catch recoverable exception in monitored 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); } }); }
public ChessMain(MChessOptions m, Assembly a, string testClassName, string unitTestName) { this.mco = m; this.testAssembly = a; this.testclass = testClassName; this.unitTestMethodName = unitTestName; this.runUnitTest = !String.IsNullOrEmpty(unitTestMethodName); this.manager = new ClrSyncManager(m); MChessChess.Init(manager, mco); TryLoadReferencedAssemblies(new[] { testAssembly }); get_entries(testAssembly); popups(m); this.manager.SetExitCallBack((c, ex) => { string msg = ""; if (ex != null) { msg = @"Child thread raised exception " + ex.Message + @" Stack trace: " + ex.StackTrace + @" "; ReportErrorAndExit(msg, c, true, ex); } ReportErrorAndExitRaw("", c, true, true, null); }); try { do_startup(); // print warning if races are disabled if (MChessChess.GetExitCode() == 0 && !(mco.preemptAccesses || mco.sober || mco.maxExecutions == 1 || !String.IsNullOrEmpty(mco.enumerateObservations))) { MChessChess.ReportWarning("Race Detection Disabled. Races May Hide Bugs.", "", false); } // RunTest loop bool moreToTest = true; while (moreToTest) { if (!MChessChess.StartTest()) { ReportErrorAndExit("Internal failure: CHESS.StartTest failed", ChessExitCode.ChessFailure, false, null); } if (MyEngine.EnvironmentVars.FlipPreemptSense) { MChessChess.PreemptionDisable(); } do_run(); if (MyEngine.EnvironmentVars.FlipPreemptSense) { MChessChess.PreemptionEnable(); } if (manager.BreakDeadlockMode) { MChessChess.EnterChess(); MChessChess.WakeNextDeadlockedThread(true, false); // we are now done with the deadlock-breaking mode! Debug.Assert(!MChessChess.IsBreakingDeadlock()); manager.BreakDeadlockMode = false; MChessChess.LeaveChess(); } moreToTest = MChessChess.EndTest(); } do_shutdown(); } catch (Exception ex) { string message = @"CHESS internal failure. " + ex.Message + @" " + ex.StackTrace + @" "; ReportErrorAndExit(message, ChessExitCode.ChessFailure, false, ex); } ReportErrorAndExit("", (ChessExitCode)MChessChess.GetExitCode(), false, null); }
// dueTime: the amount of time to delay before callback is invoked, in milliseconds. // Specify Timeout.Infinite to prevent the timer from starting. // Specify zero (0) to start the timer immediately. // period: The time interval between invocations of callback, in milliseconds. // Specify Timeout.Infinite to disable periodic signaling. // The method specified for callback should be reentrant, because it is called on ThreadPool threads. // The method can be executed simultaneously on two thread pool threads if the timer interval is less // than the time required to execute the method, or if all thread pool threads are in use and the method // is queued multiple times. public static void TimerCreateWrapper(object start) { try { TimerRoutineArg argument = (TimerRoutineArg)start; argument.inLoop = true; argument.changed = false; argument.parentSemaphore.Release(); ClrSyncManager manager = ClrSyncManager.SyncManager; manager.ThreadBegin(argument.selfSemaphore); Exception exception = null; while (true) { manager.SetMethodInfo("Timer.read"); manager.SyncVarAccess(argument.timer, MSyncVarOp.RWVAR_READWRITE); manager.CommitSyncVarAccess(); if (timer2tra[argument.timer].disposed) { // the timer only goes away when it is disposed of // it may be disabled, but a Change can reenable it break; } manager.TaskYield(); // until fairness deals with unbounded thread creation manager.TaskYield(); // we yield twice if (!argument.dueTime.Equals(TimeSpan.FromTicks(Timeout.Infinite))) { MChessChess.LeaveChess(); try { argument.callback(argument.state); } catch (Exception e) // catch recoverable exception in monitored code { exception = e; } MChessChess.EnterChess(); // If period is zero (0) or Infinite and dueTime is not Infinite, callback is invoked once; // the periodic behavior of the timer is disabled, but can be re-enabled using the Change method. } if (exception != null) { break; } if (argument.changed) { argument.changed = false; continue; } if (argument.Period.Equals(TimeSpan.FromTicks(Timeout.Infinite)) || argument.Period.Equals(TimeSpan.FromTicks(0))) { break; } } argument.inLoop = false; if (timer2tra[argument.timer].disposed) { timer2tra.Remove(argument.timer); } if (manager.BreakDeadlockMode) { MChessChess.WakeNextDeadlockedThread(false, true); } else if (exception == null) { manager.ThreadEnd(System.Threading.Thread.CurrentThread); } else { manager.Shutdown(exception); } } catch (Exception e) // catch fatal error in our code { ClrSyncManager manager = ClrSyncManager.SyncManager; manager.Shutdown(e); } }
static public bool Wrap() { ClrSyncManager manager = ClrSyncManager.SyncManager; return(manager != null && manager.IsInitialized && not_tracked > 0); }