// along with the impact of EH.
using System;
+using System.Threading;
using System.Runtime.CompilerServices;
internal class Test
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- static int AsForceInline()
+ static bool AsForceInline()
{
- return Environment.ProcessorCount;
+ return Thread.Yield();
}
- static int AsNormalInline()
+ static bool AsNormalInline()
{
- return Environment.ProcessorCount;
+ return Thread.Yield();
}
[MethodImpl(MethodImplOptions.NoInlining)]
- static int AsNoInline()
+ static bool AsNoInline()
{
- return Environment.ProcessorCount;
+ return Thread.Yield();
}
static bool FromTryCatch()
try
{
// All pinvokes should be inline, except on x64
- result = (Environment.ProcessorCount == AsNormalInline());
+ result = (Thread.Yield() == AsNormalInline());
}
catch (Exception)
{
try
{
// All pinvokes should be inline, except on x64
- result1 = (Environment.ProcessorCount == AsNormalInline());
- result2 = (Environment.ProcessorCount == AsNormalInline());
+ result1 = (Thread.Yield() == AsNormalInline());
+ result2 = (Thread.Yield() == AsNormalInline());
}
finally
{
try
{
// These two pinvokes should be inline, except on x64
- result1 = (Environment.ProcessorCount == AsNormalInline());
+ result1 = (Thread.Yield() == AsNormalInline());
}
finally
{
// These two pinvokes should *not* be inline (finally)
- result2 = (Environment.ProcessorCount == AsNormalInline());
+ result2 = (Thread.Yield() == AsNormalInline());
result = result1 && result2;
}
try
{
// These two pinvokes should be inline, except on x64
- result1 = (Environment.ProcessorCount == AsNormalInline());
+ result1 = (Thread.Yield() == AsNormalInline());
}
finally
{
try
{
// These two pinvokes should *not* be inline (finally)
- result2 = (Environment.ProcessorCount == AsNormalInline());
+ result2 = (Thread.Yield() == AsNormalInline());
}
catch (Exception)
{
static bool FromInline()
{
// These two pinvokes should be inline
- bool result = (Environment.ProcessorCount == AsForceInline());
+ bool result = (Thread.Yield() == AsForceInline());
return result;
}
static bool FromInline2()
{
// These four pinvokes should be inline
- bool result1 = (Environment.ProcessorCount == AsNormalInline());
- bool result2 = (Environment.ProcessorCount == AsForceInline());
+ bool result1 = (Thread.Yield() == AsNormalInline());
+ bool result2 = (Thread.Yield() == AsForceInline());
return result1 && result2;
}
static bool FromNoInline()
{
// The only pinvoke should be inline
- bool result = (Environment.ProcessorCount == AsNoInline());
+ bool result = (Thread.Yield() == AsNoInline());
return result;
}
static bool FromNoInline2()
{
// Three pinvokes should be inline
- bool result1 = (Environment.ProcessorCount == AsNormalInline());
- bool result2 = (Environment.ProcessorCount == AsNoInline());
+ bool result1 = (Thread.Yield() == AsNormalInline());
+ bool result2 = (Thread.Yield() == AsNoInline());
return result1 && result2;
}
// it just calls get_ProcessorCount.
//
// For the second call, the force inline works, and the
- // subsequent inline of get_ProcessorCount exposes a call
- // to the pinvoke GetProcessorCount. This pinvoke will
+ // subsequent inline of Thread.Yield exposes a call
+ // to the pinvoke YieldInternal. This pinvoke will
// not be inline.
- catch (Exception) when (Environment.ProcessorCount == AsForceInline())
+ catch (Exception) when (Thread.Yield() == AsForceInline())
{
result = true;
}
static bool FromColdCode()
{
- int pc = 0;
+ bool yield = false;
bool result1 = false;
bool result2 = false;
try
{
// This pinvoke should not be inline (cold)
- pc = Environment.ProcessorCount;
+ yield = Thread.Yield();
throw new Exception("expected");
}
catch (Exception)
// These two pinvokes should not be inline (catch)
//
// For the first call the jit won't inline the
- // wrapper, so it just calls get_ProcessorCount.
+ // wrapper, so it just calls Thread.Yield.
//
// For the second call, the force inline works, and
- // the subsequent inline of get_ProcessorCount exposes
- // a call to the pinvoke GetProcessorCount. This
+ // the subsequent inline of Thread.Yield exposes
+ // a call to the pinvoke YieldInternal. This
// pinvoke will not be inline.
- result1 = (pc == Environment.ProcessorCount);
- result2 = (pc == AsForceInline());
+ result1 = (yield == Thread.Yield());
+ result2 = (yield == AsForceInline());
}
return result1 && result2;
/// depends on the likelihood of the spin being successful and how long the wait would be but those are not accounted
/// for here.
/// </remarks>
- internal static readonly int SpinCountforSpinBeforeWait = PlatformHelper.IsSingleProcessor ? 1 : 35;
+ internal static readonly int SpinCountforSpinBeforeWait = Environment.IsSingleProcessor ? 1 : 35;
// The number of times we've spun already.
private int _count;
/// On a single-CPU machine, <see cref="SpinOnce()"/> always yields the processor. On machines with
/// multiple CPUs, <see cref="SpinOnce()"/> may yield after an unspecified number of calls.
/// </remarks>
- public bool NextSpinWillYield => _count >= YieldThreshold || PlatformHelper.IsSingleProcessor;
+ public bool NextSpinWillYield => _count >= YieldThreshold || Environment.IsSingleProcessor;
/// <summary>
/// Performs a single spin.
_count >= YieldThreshold &&
((_count >= sleep1Threshold && sleep1Threshold >= 0) || (_count - YieldThreshold) % 2 == 0)
) ||
- PlatformHelper.IsSingleProcessor)
+ Environment.IsSingleProcessor)
{
//
// We must yield.
}
#endregion
}
-
- /// <summary>
- /// A helper class to get the number of processors, it updates the numbers of processors every sampling interval.
- /// </summary>
- internal static class PlatformHelper
- {
- private const int PROCESSOR_COUNT_REFRESH_INTERVAL_MS = 30000; // How often to refresh the count, in milliseconds.
- private static volatile int s_processorCount; // The last count seen.
- private static volatile int s_lastProcessorCountRefreshTicks; // The last time we refreshed.
-
- /// <summary>
- /// Gets the number of available processors
- /// </summary>
- internal static int ProcessorCount
- {
- get
- {
- int now = Environment.TickCount;
- int procCount = s_processorCount;
- if (procCount == 0 || (now - s_lastProcessorCountRefreshTicks) >= PROCESSOR_COUNT_REFRESH_INTERVAL_MS)
- {
- s_processorCount = procCount = Environment.ProcessorCount;
- s_lastProcessorCountRefreshTicks = now;
- }
-
- Debug.Assert(procCount > 0,
- "Processor count should be greater than 0.");
-
- return procCount;
- }
- }
-
- /// <summary>
- /// Gets whether the current machine has only a single processor.
- /// </summary>
- /// <remarks>This typically does not change on a machine, so it's checked only once.</remarks>
- internal static readonly bool IsSingleProcessor = ProcessorCount == 1;
- }
}