Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadStateException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Timeout.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\TimeoutHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Timer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitHandleCannotBeOpenedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ThreadStaticAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ThrowHelper.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,10 @@ public bool Set()
throw Win32Marshal.GetExceptionForLastWin32Error();
return res;
}

internal static bool Set(SafeWaitHandle waitHandle)
{
return Interop.Kernel32.SetEvent(waitHandle);
}
}
}
862 changes: 862 additions & 0 deletions src/System.Private.CoreLib/shared/System/Threading/Timer.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
<Compile Include="System\Diagnostics\StackFrame.CoreRT.cs" />
<Compile Include="System\Diagnostics\StackFrameExtensions.cs" />
<Compile Include="System\Diagnostics\StackTrace.CoreRT.cs" />
<Compile Include="System\Diagnostics\Tracing\EventPipeController.cs" />
<Compile Include="System\Diagnostics\Tracing\EventSource_CoreRT.cs" />
<Compile Include="System\Diagnostics\Tracing\FrameworkEventSource.cs" />
<Compile Include="System\Diagnostics\Tracing\UnsafeNativeMethods.cs" />
Expand Down Expand Up @@ -292,7 +293,6 @@
<Compile Include="System\Threading\Tasks\AsyncCausalityTracer.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
<Compile Include="System\Threading\ThreadPool.CoreRT.cs" />
<Compile Include="System\Threading\ThreadPoolCallbackWrapper.cs" />
<Compile Include="System\Threading\Timer.cs" />
<Compile Include="System\Threading\Volatile.cs" />
<Compile Include="System\Threading\WaitHandle.cs" />
<Compile Include="System\Threading\WaitHandleArray.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Diagnostics.Tracing
{
sealed internal class EventPipeController
{
public static bool Initializing { get => true; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public static class Keywords
public const EventKeywords ThreadTransfer = (EventKeywords)0x0010;
}

public static bool IsInitialized { get => true; }

public bool IsEnabled(EventLevel level, EventKeywords keywords)
{
return false;
Expand All @@ -31,6 +33,14 @@ public void ThreadPoolEnqueueWorkObject(object workID)
public void ThreadPoolDequeueWorkObject(object workID)
{
}

public void ThreadTransferSendObj(object id, int kind, string info, bool multiDequeues, int intInfo1, int intInfo2)
{
}

public void ThreadTransferReceiveObj(object id, int kind, string info)
{
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ public bool Set()
}
}

internal static bool Set(SafeWaitHandle waitHandle)
{
waitHandle.DangerousAddRef();
try
{
WaitSubsystem.SetEvent(waitHandle.DangerousGetHandle());
return true;
}
finally
{
waitHandle.DangerousRelease();
}
}

private SafeWaitHandle ValidateHandle()
{
// The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
Expand Down
40 changes: 8 additions & 32 deletions src/System.Private.CoreLib/src/System/Threading/Timer.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ internal partial class TimerQueue
/// </summary>
private static volatile int s_nextTimerDuration;

private void SetTimer(uint actualDuration)
private TimerQueue(int id)
{
// This function is called with the TimerQueue lock acquired
Debug.Assert(Lock.IsAcquired);
}

private bool SetTimer(uint actualDuration)
{
// Note: AutoResetEvent.WaitOne takes an Int32 value as a timeout.
// The TimerQueue code ensures that timer duration is not greater than max Int32 value
Debug.Assert(actualDuration <= (uint)int.MaxValue);
Expand All @@ -50,14 +51,16 @@ private void SetTimer(uint actualDuration)
{
s_timerEvent.Set();
}

return true;
}


/// <summary>
/// This method is executed on a dedicated a timer thread. Its purpose is
/// to handle timer request and notify the TimerQueue when a timer expires.
/// </summary>
private static void TimerThread()
private void TimerThread()
{
int currentTimerInterval;

Expand Down Expand Up @@ -92,7 +95,7 @@ private static void TimerThread()
// Check whether TimerQueue needs to process expired timers.
if (timerHasExpired)
{
Instance.FireNextTimers();
FireNextTimers();

// When FireNextTimers() installs a new timer, it also sets the timer event.
// Reset the event so the timer thread is not woken up right away unnecessary.
Expand All @@ -116,31 +119,4 @@ private static int TickCount
}
}
}

internal sealed partial class TimerQueueTimer
{
private void SignalNoCallbacksRunning()
{
object toSignal = _notifyWhenNoCallbacksRunning;
Debug.Assert(toSignal is WaitHandle || toSignal is Task<bool>);

if (toSignal is WaitHandle wh)
{
SafeWaitHandle waitHandle = wh.SafeWaitHandle;
waitHandle.DangerousAddRef();
try
{
WaitSubsystem.SetEvent(waitHandle.DangerousGetHandle());
}
finally
{
waitHandle.DangerousRelease();
}
}
else
{
((Task<bool>)toSignal).TrySetResult(true);
}
}
}
}
33 changes: 12 additions & 21 deletions src/System.Private.CoreLib/src/System/Threading/Timer.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,38 @@ namespace System.Threading
internal partial class TimerQueue
{
private IntPtr _nativeTimer;
private readonly int _id;

private TimerQueue(int id)
{
_id = id;
}

[NativeCallable(CallingConvention = CallingConvention.StdCall)]
private static void TimerCallback(IntPtr instance, IntPtr context, IntPtr timer)
{
int id = (int)context;
var wrapper = ThreadPoolCallbackWrapper.Enter();
Instance.FireNextTimers();
Instances[id].FireNextTimers();
wrapper.Exit();
}

private unsafe void SetTimer(uint actualDuration)
private unsafe bool SetTimer(uint actualDuration)
{
if (_nativeTimer == IntPtr.Zero)
{
IntPtr nativeCallback = AddrofIntrinsics.AddrOf<Interop.mincore.TimerCallback>(TimerCallback);

_nativeTimer = Interop.mincore.CreateThreadpoolTimer(nativeCallback, IntPtr.Zero, IntPtr.Zero);
_nativeTimer = Interop.mincore.CreateThreadpoolTimer(nativeCallback, (IntPtr)_id, IntPtr.Zero);
if (_nativeTimer == IntPtr.Zero)
throw new OutOfMemoryException();
}

// Negative time indicates the amount of time to wait relative to the current time, in 100 nanosecond units
long dueTime = -10000 * (long)actualDuration;
Interop.mincore.SetThreadpoolTimer(_nativeTimer, &dueTime, 0, 0);

return true;
}

//
Expand All @@ -62,22 +71,4 @@ private static int TickCount
}
}
}

internal sealed partial class TimerQueueTimer
{
private void SignalNoCallbacksRunning()
{
object toSignal = _notifyWhenNoCallbacksRunning;
Debug.Assert(toSignal is WaitHandle || toSignal is Task<bool>);

if (toSignal is WaitHandle wh)
{
Interop.Kernel32.SetEvent(wh.SafeWaitHandle);
}
else
{
((Task<bool>)toSignal).TrySetResult(true);
}
}
}
}
Loading