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); }
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); } }); }
// 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); } }