Skip to content

Commit 20157b5

Browse files
committed
Address PR feedback
1 parent 68040cb commit 20157b5

File tree

7 files changed

+37
-86
lines changed

7 files changed

+37
-86
lines changed

src/libraries/System.Private.CoreLib/src/Resources/Strings.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3411,7 +3411,7 @@
34113411
<value>The timeout must represent a value between -1 and Int32.MaxValue, inclusive.</value>
34123412
</data>
34133413
<data name="SemaphoreSlim_Wait_TimeSpanTimeoutWrong" xml:space="preserve">
3414-
<value>The timeout must represent a value between -1 and the maximum allowed timer duration.</value>
3414+
<value>The timeout must be greater than or equal to -1.</value>
34153415
</data>
34163416
<data name="Serialization_BadParameterInfo" xml:space="preserve">
34173417
<value>Non existent ParameterInfo. Position bigger than member's parameters length.</value>

src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
520520
// period of time. The timeout adjustments only take effect when and if we actually
521521
// decide to block in the kernel below.
522522

523-
startTime = TimeoutHelper.GetTime();
523+
startTime = (uint)Environment.TickCount;
524524
bNeedTimeoutAdjustment = true;
525525
}
526526

@@ -558,7 +558,8 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
558558
// update timeout (delays in wait commencement are due to spinning and/or spurious wakeups from other waits being canceled)
559559
if (bNeedTimeoutAdjustment)
560560
{
561-
realMillisecondsTimeout = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
561+
// TimeoutHelper.UpdateTimeOut returns a long but the value is capped as millisecondsTimeout is an int.
562+
realMillisecondsTimeout = (int)TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
562563
if (realMillisecondsTimeout <= 0)
563564
return false;
564565
}

src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public void Wait()
178178
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
179179
#endif
180180
// Call wait with infinite timeout
181-
Wait(Timeout.UnsignedInfinite, CancellationToken.None);
181+
Wait(Timeout.Infinite, CancellationToken.None);
182182
}
183183

184184
/// <summary>
@@ -198,7 +198,7 @@ public void Wait(CancellationToken cancellationToken)
198198
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
199199
#endif
200200
// Call wait with infinite timeout
201-
Wait(Timeout.UnsignedInfinite, cancellationToken);
201+
Wait(Timeout.Infinite, cancellationToken);
202202
}
203203

204204
/// <summary>
@@ -211,8 +211,7 @@ public void Wait(CancellationToken cancellationToken)
211211
/// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
212212
/// otherwise, false.</returns>
213213
/// <exception cref="ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
214-
/// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
215-
/// than maximum allowed timer duration.</exception>
214+
/// number other than -1 milliseconds, which represents an infinite time-out.</exception>
216215
[UnsupportedOSPlatform("browser")]
217216
public bool Wait(TimeSpan timeout)
218217
{
@@ -221,14 +220,14 @@ public bool Wait(TimeSpan timeout)
221220
#endif
222221
// Validate the timeout
223222
long totalMilliseconds = (long)timeout.TotalMilliseconds;
224-
if (totalMilliseconds < -1 || totalMilliseconds > Timer.MaxSupportedTimeout)
223+
if (totalMilliseconds < -1)
225224
{
226225
throw new ArgumentOutOfRangeException(
227226
nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeSpanTimeoutWrong);
228227
}
229228

230229
// Call wait with the timeout milliseconds
231-
return Wait(totalMilliseconds == Timeout.Infinite ? Timeout.UnsignedInfinite : (uint)totalMilliseconds, CancellationToken.None);
230+
return Wait(totalMilliseconds, CancellationToken.None);
232231
}
233232

234233
/// <summary>
@@ -244,8 +243,7 @@ public bool Wait(TimeSpan timeout)
244243
/// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
245244
/// otherwise, false.</returns>
246245
/// <exception cref="ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
247-
/// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
248-
/// than maximum allowed timer duration.</exception>
246+
/// number other than -1 milliseconds, which represents an infinite time-out.</exception>
249247
/// <exception cref="OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
250248
[UnsupportedOSPlatform("browser")]
251249
public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
@@ -255,14 +253,14 @@ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
255253
#endif
256254
// Validate the timeout
257255
long totalMilliseconds = (long)timeout.TotalMilliseconds;
258-
if (totalMilliseconds < -1 || totalMilliseconds > Timer.MaxSupportedTimeout)
256+
if (totalMilliseconds < -1)
259257
{
260258
throw new ArgumentOutOfRangeException(
261259
nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeSpanTimeoutWrong);
262260
}
263261

264262
// Call wait with the timeout milliseconds
265-
return Wait(totalMilliseconds == Timeout.Infinite ? Timeout.UnsignedInfinite : (uint)totalMilliseconds, cancellationToken);
263+
return Wait(totalMilliseconds, cancellationToken);
266264
}
267265

268266
/// <summary>
@@ -309,7 +307,7 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
309307
nameof(millisecondsTimeout), millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
310308
}
311309

312-
return Wait(millisecondsTimeout == Timeout.Infinite ? Timeout.UnsignedInfinite : (uint)millisecondsTimeout, cancellationToken);
310+
return Wait(millisecondsTimeout, cancellationToken);
313311
}
314312

315313
/// <summary>
@@ -323,7 +321,7 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
323321
/// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>; otherwise, false.</returns>
324322
/// <exception cref="OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
325323
[UnsupportedOSPlatform("browser")]
326-
private bool Wait(uint millisecondsTimeout, CancellationToken cancellationToken)
324+
private bool Wait(long millisecondsTimeout, CancellationToken cancellationToken)
327325
{
328326
CheckDispose();
329327
#if FEATURE_WASM_MANAGED_THREADS
@@ -339,9 +337,9 @@ private bool Wait(uint millisecondsTimeout, CancellationToken cancellationToken)
339337
}
340338

341339
long startTime = 0;
342-
if (millisecondsTimeout != Timeout.UnsignedInfinite && millisecondsTimeout > 0)
340+
if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
343341
{
344-
startTime = TimeoutHelper.GetTime64();
342+
startTime = Environment.TickCount64;
345343
}
346344

347345
bool waitSuccessful = false;
@@ -465,7 +463,7 @@ private bool Wait(uint millisecondsTimeout, CancellationToken cancellationToken)
465463
/// <param name="cancellationToken">The CancellationToken to observe.</param>
466464
/// <returns>true if the monitor received a signal, false if the timeout expired</returns>
467465
[UnsupportedOSPlatform("browser")]
468-
private bool WaitUntilCountOrTimeout(uint millisecondsTimeout, long startTime, CancellationToken cancellationToken)
466+
private bool WaitUntilCountOrTimeout(long millisecondsTimeout, long startTime, CancellationToken cancellationToken)
469467
{
470468
#if TARGET_WASI
471469
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException(); // TODO remove with https://github.com/dotnet/runtime/pull/107185
@@ -481,7 +479,7 @@ private bool WaitUntilCountOrTimeout(uint millisecondsTimeout, long startTime, C
481479
// Since Monitor.Wait will handle the actual wait and it accepts an int timeout,
482480
// we may need to cap the timeout to int.MaxValue.
483481
bool timeoutIsCapped = false;
484-
if (millisecondsTimeout != Timeout.UnsignedInfinite)
482+
if (millisecondsTimeout != Timeout.Infinite)
485483
{
486484
long remainingWaitMilliseconds = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
487485
if (remainingWaitMilliseconds <= 0)
@@ -531,7 +529,7 @@ private bool WaitUntilCountOrTimeout(uint millisecondsTimeout, long startTime, C
531529
/// <returns>A task that will complete when the semaphore has been entered.</returns>
532530
public Task WaitAsync()
533531
{
534-
return WaitAsync(Timeout.UnsignedInfinite, default);
532+
return WaitAsync(Timeout.Infinite, default);
535533
}
536534

537535
/// <summary>
@@ -547,7 +545,7 @@ public Task WaitAsync()
547545
/// </exception>
548546
public Task WaitAsync(CancellationToken cancellationToken)
549547
{
550-
return WaitAsync(Timeout.UnsignedInfinite, cancellationToken);
548+
return WaitAsync(Timeout.Infinite, cancellationToken);
551549
}
552550

553551
/// <summary>
@@ -619,14 +617,14 @@ public Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToke
619617
{
620618
// Validate the timeout
621619
long totalMilliseconds = (long)timeout.TotalMilliseconds;
622-
if (totalMilliseconds < -1 || totalMilliseconds > Timer.MaxSupportedTimeout)
620+
if (totalMilliseconds < -1)
623621
{
624622
throw new ArgumentOutOfRangeException(
625623
nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeSpanTimeoutWrong);
626624
}
627625

628626
// Call wait with the timeout milliseconds
629-
return WaitAsync(totalMilliseconds == Timeout.Infinite ? Timeout.UnsignedInfinite : (uint)totalMilliseconds, cancellationToken);
627+
return WaitAsync(totalMilliseconds, cancellationToken);
630628
}
631629

632630
/// <summary>
@@ -655,7 +653,7 @@ public Task<bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellat
655653
nameof(millisecondsTimeout), millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
656654
}
657655

658-
return WaitAsync(millisecondsTimeout == Timeout.Infinite ? Timeout.UnsignedInfinite : (uint)millisecondsTimeout, cancellationToken);
656+
return WaitAsync(millisecondsTimeout, cancellationToken);
659657
}
660658

661659
/// <summary>
@@ -673,7 +671,7 @@ public Task<bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellat
673671
/// </returns>
674672
/// <exception cref="ObjectDisposedException">The current instance has already been
675673
/// disposed.</exception>
676-
private Task<bool> WaitAsync(uint millisecondsTimeout, CancellationToken cancellationToken)
674+
private Task<bool> WaitAsync(long millisecondsTimeout, CancellationToken cancellationToken)
677675
{
678676
CheckDispose();
679677

@@ -702,7 +700,7 @@ private Task<bool> WaitAsync(uint millisecondsTimeout, CancellationToken cancell
702700
{
703701
Debug.Assert(m_currentCount == 0, "m_currentCount should never be negative");
704702
TaskNode asyncWaiter = CreateAndAddAsyncWaiter();
705-
return (millisecondsTimeout == Timeout.UnsignedInfinite && !cancellationToken.CanBeCanceled) ?
703+
return (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled) ?
706704
asyncWaiter :
707705
WaitUntilCountOrTimeoutAsync(asyncWaiter, millisecondsTimeout, cancellationToken);
708706
}
@@ -767,13 +765,13 @@ private bool RemoveAsyncWaiter(TaskNode task)
767765
/// <param name="millisecondsTimeout">The timeout.</param>
768766
/// <param name="cancellationToken">The cancellation token.</param>
769767
/// <returns>The task to return to the caller.</returns>
770-
private async Task<bool> WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, uint millisecondsTimeout, CancellationToken cancellationToken)
768+
private async Task<bool> WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, long millisecondsTimeout, CancellationToken cancellationToken)
771769
{
772770
Debug.Assert(asyncWaiter is not null, "Waiter should have been constructed");
773771
Debug.Assert(Monitor.IsEntered(m_lockObjAndDisposed), "Requires the lock be held");
774772

775773
await ((Task)asyncWaiter.WaitAsync(
776-
TimeSpan.FromMilliseconds(millisecondsTimeout == Timeout.UnsignedInfinite ? (long)Timeout.Infinite : (long)millisecondsTimeout),
774+
TimeSpan.FromMilliseconds(millisecondsTimeout),
777775
cancellationToken)).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
778776

779777
if (cancellationToken.IsCancellationRequested)

src/libraries/System.Private.CoreLib/src/System/Threading/SpinLock.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken)
290290
uint startTime = 0;
291291
if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout != 0)
292292
{
293-
startTime = TimeoutHelper.GetTime();
293+
startTime = (uint)Environment.TickCount;
294294
}
295295

296296
if (IsThreadOwnerTrackingEnabled)

src/libraries/System.Private.CoreLib/src/System/Threading/SpinWait.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ public static bool SpinUntil(Func<bool> condition, int millisecondsTimeout)
315315
uint startTime = 0;
316316
if (millisecondsTimeout != 0 && millisecondsTimeout != Timeout.Infinite)
317317
{
318-
startTime = TimeoutHelper.GetTime();
318+
startTime = (uint)Environment.TickCount;
319319
}
320320
SpinWait spinner = default;
321321
while (!condition())
@@ -329,7 +329,7 @@ public static bool SpinUntil(Func<bool> condition, int millisecondsTimeout)
329329

330330
if (millisecondsTimeout != Timeout.Infinite && spinner.NextSpinWillYield)
331331
{
332-
if (millisecondsTimeout <= (TimeoutHelper.GetTime() - startTime))
332+
if (millisecondsTimeout <= (uint)Environment.TickCount - startTime)
333333
{
334334
return false;
335335
}

src/libraries/System.Private.CoreLib/src/System/Threading/TimeoutHelper.cs

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,77 +6,35 @@
66
namespace System.Threading
77
{
88
/// <summary>
9-
/// A helper class to capture a start time using <see cref="Environment.TickCount"/> as a time in milliseconds.
10-
/// Also updates a given timeout by subtracting the current time from the start time.
9+
/// A helper class to update a given timeout by subtracting the current time from the start time.
1110
/// </summary>
1211
internal static class TimeoutHelper
1312
{
14-
/// <summary>
15-
/// Returns <see cref="Environment.TickCount"/> as a start time in milliseconds as a <see cref="uint"/>.
16-
/// <see cref="Environment.TickCount"/> rolls over from positive to negative every ~25 days, then ~25 days to back to positive again.
17-
/// <see cref="uint"/> is used to ignore the sign and double the range to 50 days.
18-
/// </summary>
19-
public static uint GetTime()
20-
{
21-
return (uint)Environment.TickCount;
22-
}
23-
24-
/// <summary>
25-
/// Returns <see cref="Environment.TickCount64"/> as a start time in milliseconds.
26-
/// </summary>
27-
public static long GetTime64()
28-
{
29-
return Environment.TickCount64;
30-
}
31-
3213
/// <summary>
3314
/// Helper function to measure and update the elapsed time
3415
/// </summary>
3516
/// <param name="startTime"> The first time (in milliseconds) observed when the wait started</param>
3617
/// <param name="originalWaitMillisecondsTimeout">The original wait timeout in milliseconds</param>
3718
/// <returns>The new wait time in milliseconds</returns>
38-
public static int UpdateTimeOut(uint startTime, int originalWaitMillisecondsTimeout)
19+
public static long UpdateTimeOut(long startTime, long originalWaitMillisecondsTimeout)
3920
{
4021
// The function must be called in case the time out is not infinite
4122
Debug.Assert(originalWaitMillisecondsTimeout != Timeout.Infinite);
4223

43-
uint elapsedMilliseconds = (GetTime() - startTime);
24+
ulong elapsedMilliseconds = (ulong)(Environment.TickCount64 - startTime);
4425

45-
// Check the elapsed milliseconds is greater than max int because this property is uint
46-
if (elapsedMilliseconds > int.MaxValue)
26+
if (elapsedMilliseconds > long.MaxValue)
4727
{
4828
return 0;
4929
}
5030

51-
// Subtract the elapsed time from the current wait time
52-
int currentWaitTimeout = originalWaitMillisecondsTimeout - (int)elapsedMilliseconds;
31+
long currentWaitTimeout = originalWaitMillisecondsTimeout - (long)elapsedMilliseconds;
5332
if (currentWaitTimeout <= 0)
5433
{
5534
return 0;
5635
}
5736

5837
return currentWaitTimeout;
5938
}
60-
61-
/// <summary>
62-
/// Helper function to measure and update the elapsed time
63-
/// </summary>
64-
/// <param name="startTime"> The first time (in milliseconds) observed when the wait started</param>
65-
/// <param name="originalWaitMillisecondsTimeout">The original wait timeout in milliseconds</param>
66-
/// <returns>The new wait time in milliseconds</returns>
67-
public static long UpdateTimeOut(long startTime, uint originalWaitMillisecondsTimeout)
68-
{
69-
// The function must be called in case the time out is not infinite
70-
Debug.Assert(originalWaitMillisecondsTimeout != Timeout.UnsignedInfinite);
71-
72-
long elapsedMilliseconds = GetTime64() - startTime;
73-
74-
if (originalWaitMillisecondsTimeout <= elapsedMilliseconds)
75-
{
76-
return 0;
77-
}
78-
79-
return originalWaitMillisecondsTimeout - elapsedMilliseconds;
80-
}
8139
}
8240
}

0 commit comments

Comments
 (0)