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 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 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); } }); }
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 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 long not_tracked = 0; // 0 by default, means thread is *NOT* tracked by CHESS public WrapperSentry() { MChessChess.EnterChess(); }
// variable-range parallel for loop helper internal static OTasks.ParallelLoopResult?ParallelForHelper( Func <Range> prologue, bool singlethread, string name, global::System.Action <long> body, Helper.SimpleDel <OTasks.ParallelLoopResult?> orig) { return (Helper.SimpleContextExposingWrap( delegate(ClrSyncManager manager, ref IDisposable protectingcontext) { Range range = new Range(); // do prologue outside chess... and switch protecting context MChessChess.LeaveChess(); protectingcontext.Dispose(); Exception ex = null; try { range = prologue(); } catch (Exception e) // catch recoverable exception in user code { ex = e; } IDisposable pc = _ProtectingThreadContext.Acquire(); MChessChess.EnterChess(); if (ex != null) { global::System.Diagnostics.Debug.Fail("Not implemented: exceptions in enumerators of Parallel foreach"); throw ex; } if (range.to <= range.from) // empty loop { return orig(); } long split; if (!singlethread) { split = range.minsplit + manager.Choose((int)(range.maxsplit - range.minsplit + 1)); } else { split = (manager.Choose(2) == 0) ? range.minsplit : range.maxsplit; } MChessChess.TraceEvent(name + "(" + range.from + "," + range.to + "), split " + split); SimplePartitioner <long> partitioner = new SimplePartitioner <long>( manager, range.from, range.to, split, (long i) => { return i; }, true); // store protecting context partitioner.protectingcontext = pc; // TODO better job here OTasks.ParallelOptions options = new OTasks.ParallelOptions(); options.MaxDegreeOfParallelism = 2; OTasks.ParallelLoopResult result = OTasks.Parallel.ForEach <long>(partitioner, options, partitioner.WrapBody(body)); // switch protecting context back partitioner.protectingcontext.Dispose(); protectingcontext = _ProtectingThreadContext.Acquire(); return result; }, orig )); }