From c43f27e0aebe8adeb12a60a3747fd85daf14aaa4 Mon Sep 17 00:00:00 2001 From: Eduardo Manuel Velarde Polar Date: Wed, 5 Jun 2024 16:29:48 -0700 Subject: [PATCH 1/3] Add the new lock type to Timer.cs --- .../src/System/Threading/Timer.cs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs index 24fa9f8f8e0341..017729d4f96bfc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs @@ -171,6 +171,9 @@ private bool EnsureTimerFiresBy(uint requestedDuration) // need to look at the long list because the current time will be <= _currentAbsoluteThreshold. private const int ShortTimersThresholdMilliseconds = 333; + // Lock shared by the TimerQueue instances + public Lock SharedLock { get; } = new Lock(); + // Fire any timers that have expired, and update the native timer to schedule the rest of them. // We're in a thread pool work item here, and if there are multiple timers to be fired, we want // to queue all but the first one. The first may can then be invoked synchronously or queued, @@ -181,7 +184,7 @@ private void FireNextTimers() // are queued to the ThreadPool. TimerQueueTimer? timerToFireOnThisThread = null; - lock (this) + lock (SharedLock) { // Since we got here, that means our previous timer has fired. _isTimerScheduled = false; @@ -540,7 +543,7 @@ internal bool Change(uint dueTime, uint period) { bool success; - lock (_associatedTimerQueue) + lock (_associatedTimerQueue.SharedLock) { if (_canceled) { @@ -567,7 +570,7 @@ internal bool Change(uint dueTime, uint period) public void Dispose() { - lock (_associatedTimerQueue) + lock (_associatedTimerQueue.SharedLock) { if (!_canceled) { @@ -584,7 +587,7 @@ public bool Dispose(WaitHandle toSignal) bool success; bool shouldSignal = false; - lock (_associatedTimerQueue) + lock (_associatedTimerQueue.SharedLock) { if (_canceled) { @@ -608,7 +611,7 @@ public bool Dispose(WaitHandle toSignal) public ValueTask DisposeAsync() { - lock (_associatedTimerQueue) + lock (_associatedTimerQueue.SharedLock) { object? notifyWhenNoCallbacksRunning = _notifyWhenNoCallbacksRunning; @@ -668,9 +671,9 @@ public ValueTask DisposeAsync() internal void Fire(bool isThreadPool = false) { - bool canceled = false; + bool canceled; - lock (_associatedTimerQueue) + lock (_associatedTimerQueue.SharedLock) { canceled = _canceled; if (!canceled) @@ -683,7 +686,7 @@ internal void Fire(bool isThreadPool = false) CallCallback(isThreadPool); bool shouldSignal; - lock (_associatedTimerQueue) + lock (_associatedTimerQueue.SharedLock) { _callbacksRunning--; shouldSignal = _canceled && _callbacksRunning == 0 && _notifyWhenNoCallbacksRunning != null; @@ -943,7 +946,7 @@ public static long ActiveCount long count = 0; foreach (TimerQueue queue in TimerQueue.Instances) { - lock (queue) + lock (queue.SharedLock) { count += queue.ActiveCount; } From a7d8f926d1ba106d99e43749f4dca1740db095b4 Mon Sep 17 00:00:00 2001 From: Eduardo Manuel Velarde Polar Date: Wed, 5 Jun 2024 16:54:06 -0700 Subject: [PATCH 2/3] Change SharedLock to internal --- .../System.Private.CoreLib/src/System/Threading/Timer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs index 017729d4f96bfc..af98872e40d7da 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs @@ -172,7 +172,7 @@ private bool EnsureTimerFiresBy(uint requestedDuration) private const int ShortTimersThresholdMilliseconds = 333; // Lock shared by the TimerQueue instances - public Lock SharedLock { get; } = new Lock(); + internal Lock SharedLock { get; } = new Lock(); // Fire any timers that have expired, and update the native timer to schedule the rest of them. // We're in a thread pool work item here, and if there are multiple timers to be fired, we want From 5a6ceb5d54b31f1f283079959292ebc090cf31af Mon Sep 17 00:00:00 2001 From: Eduardo Velarde <32459232+eduardo-vp@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:00:40 -0700 Subject: [PATCH 3/3] Update src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs Co-authored-by: Koundinya Veluri --- .../System.Private.CoreLib/src/System/Threading/Timer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs index af98872e40d7da..b9b825711fa975 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs @@ -171,7 +171,7 @@ private bool EnsureTimerFiresBy(uint requestedDuration) // need to look at the long list because the current time will be <= _currentAbsoluteThreshold. private const int ShortTimersThresholdMilliseconds = 333; - // Lock shared by the TimerQueue instances + // Lock shared by the TimerQueue and associated TimerQueueTimer instances internal Lock SharedLock { get; } = new Lock(); // Fire any timers that have expired, and update the native timer to schedule the rest of them.