Skip to content
Merged
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
10 changes: 6 additions & 4 deletions src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
<ILLinkTrimAssembly>true</ILLinkTrimAssembly>
<ILLinkDescriptorsXml>$(IntermediateOutputPath)ILLink.Descriptors.xml</ILLinkDescriptorsXml>
<ILLinkDirectory>$(MSBuildThisFileDirectory)src\ILLink\</ILLinkDirectory>

<FeaturePortableThreadPool Condition="'$(TargetsBrowser)' != 'true'">true</FeaturePortableThreadPool>
<FeaturePortableTimer Condition="'$(TargetsBrowser)' != 'true'">true</FeaturePortableTimer>
<FeatureSingleThread Condition="'$(TargetsBrowser)' == 'true'">true</FeatureSingleThread>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -303,6 +299,12 @@
<ItemGroup Condition="'$(FeatureObjCMarshal)' == 'true'">
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ObjectiveCMarshal.CoreCLR.cs" />
</ItemGroup>

<!-- Enable unsupported browser warnings -->
<ItemGroup Condition="'$(TargetsBrowser)' == 'true' or '$(TargetsAnyOS)' == 'true'">
<SupportedPlatform Include="browser"/>
</ItemGroup>

<!-- Include additional sources shared files in the compilation -->
<Import Project="$(LibrariesProjectRoot)\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems" Label="Shared" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ private void StartCallback()
/// </summary>
public static void SpinWait(int iterations)
{
if (Thread.IsSingleThreaded) return;

if (iterations < SpinWaitCoopThreshold)
{
SpinWaitInternal(iterations);
Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/clr.featuredefines.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<FeaturePortableEntryPoints>false</FeaturePortableEntryPoints>
<FeaturePortableHelpers>false</FeaturePortableHelpers>
<ProfilingSupportedBuild>true</ProfilingSupportedBuild>
<FeaturePortableThreadPool>true</FeaturePortableThreadPool>
<FeaturePortableTimer>true</FeaturePortableTimer>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetsAndroid)' == 'true' OR '$(Configuration)' == 'debug' OR '$(Configuration)' == 'checked'">
Expand All @@ -15,6 +17,13 @@
<FeaturePortableEntryPoints>true</FeaturePortableEntryPoints>
<FeaturePortableHelpers>true</FeaturePortableHelpers>
<FeatureInterpreter>true</FeatureInterpreter>
<FeatureWasmManagedThreads Condition="'$(WasmEnableThreads)' == 'true'">true</FeatureWasmManagedThreads>

<!-- single thread -->
<FeatureSingleThread Condition="'$(WasmEnableThreads)' != 'true'">true</FeatureSingleThread>
<FeaturePortableTimer Condition="'$(WasmEnableThreads)' != 'true'">false</FeaturePortableTimer>
<FeaturePortableThreadPool Condition="'$(WasmEnableThreads)' != 'true'">false</FeaturePortableThreadPool>
<!-- until we implement ST event pipe for CoreCLR -->
<FeaturePerfTracing>false</FeaturePerfTracing>
</PropertyGroup>

Expand Down Expand Up @@ -56,6 +65,8 @@
<DefineConstants Condition="'$(FeatureInterpreter)' == 'true'">$(DefineConstants);FEATURE_INTERPRETER</DefineConstants>
<DefineConstants Condition="'$(FeaturePortableEntryPoints)' == 'true'">$(DefineConstants);FEATURE_PORTABLE_ENTRYPOINTS</DefineConstants>
<DefineConstants Condition="'$(FeaturePortableHelpers)' == 'true'">$(DefineConstants);FEATURE_PORTABLE_HELPERS</DefineConstants>
<DefineConstants Condition="'$(FeatureWasmManagedThreads)' == 'true'">$(DefineConstants);FEATURE_WASM_MANAGED_THREADS</DefineConstants>
<DefineConstants Condition="'$(FeatureSingleThread)' == 'true'">$(DefineConstants);FEATURE_SINGLE_THREADED</DefineConstants>

<DefineConstants Condition="'$(ProfilingSupportedBuild)' == 'true'">$(DefineConstants);PROFILING_SUPPORTED</DefineConstants>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ private static bool GetLinqExpressionsBuiltWithIsInterpretingOnly()
// heavily on Reflection.Emit
public static bool IsXmlDsigXsltTransformSupported => !PlatformDetection.IsInAppContainer && IsReflectionEmitSupported;

public static bool IsPreciseGcSupported => !IsMonoRuntime;
public static bool IsPreciseGcSupported => !IsMonoRuntime
&& !IsBrowser; // TODO-WASM: https://github.com/dotnet/runtime/issues/114096

public static bool IsRareEnumsSupported => !IsNativeAot;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public XmlReader CreateDecryptingXmlReader(Stream input, XmlReaderSettings? sett
protected virtual XmlReader DecryptDocumentAndCreateXmlReader(XmlDocument document)
{
#if !NETSTANDARD2_1 && !NETSTANDARD2_0 && !NETFRAMEWORK // TODO remove with https://github.com/dotnet/runtime/pull/107185
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException();
if (OperatingSystem.IsWasi() || OperatingSystem.IsBrowser()) throw new PlatformNotSupportedException();
#else
#pragma warning disable CA1416
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void Notify(ServiceState state)
}

#if !NETSTANDARD2_1 && !NETSTANDARD2_0 && !NETFRAMEWORK // TODO remove with https://github.com/dotnet/runtime/pull/107185
if (OperatingSystem.IsWasi()) throw new PlatformNotSupportedException();
if (OperatingSystem.IsWasi() || OperatingSystem.IsBrowser()) throw new PlatformNotSupportedException();
#else
#pragma warning disable CA1416
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

namespace System.Collections.Concurrent.Tests
{
[ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public class BlockingCollectionCancellationTests
{
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void InternalCancellation_CompleteAdding_Negative()
{
BlockingCollection<int> coll1 = new BlockingCollection<int>();
Expand All @@ -26,7 +27,7 @@ public static void InternalCancellation_CompleteAdding_Negative()
}

//This tests that Take/TryTake wake up correctly if CompleteAdding() is called while waiting
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void InternalCancellation_WakingUp()
{
for (int test = 0; test < 2; test++)
Expand Down Expand Up @@ -60,7 +61,7 @@ public static void InternalCancellation_WakingUp()
}
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void ExternalCancel_Negative()
{
BlockingCollection<int> bc = new BlockingCollection<int>(); //empty collection.
Expand Down Expand Up @@ -96,7 +97,7 @@ public static void ExternalCancel_Negative()
cs.Token);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void ExternalCancel_AddToAny()
{
for (int test = 0; test < 3; test++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
namespace System.Collections.Concurrent.Tests
{
/// <summary>The class that contains the unit tests of the BlockingCollection.</summary>
[ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public class BlockingCollectionTests
{
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void TestBasicScenarios()
{
BlockingCollection<int> bc = new BlockingCollection<int>(3);
Expand Down Expand Up @@ -53,7 +54,7 @@ public static void TestBasicScenarios()
/// BlockingCollection throws InvalidOperationException when calling CompleteAdding even after adding and taking all elements
/// </summary>
/// <returns></returns>
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void TestBugFix544259()
{
int count = 8;
Expand Down Expand Up @@ -88,7 +89,7 @@ public static void TestBugFix544259()
// Since the change to wait as part of CTS.Dispose, the ODE no longer occurs
// but we keep the test as a good example of how cleanup of linkedCTS must be carefully handled
// to prevent users of the source CTS mistakenly calling methods on disposed targets.
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void TestBugFix626345()
{
const int noOfProducers = 1;
Expand Down Expand Up @@ -152,7 +153,7 @@ public static void TestBugFix626345()
/// <summary>
/// Making sure if TryTakeFromAny succeeds, it returns the correct index
/// </summary>
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void TestBugFix914998()
{
var producer1 = new BlockingCollection<int>();
Expand Down Expand Up @@ -252,7 +253,7 @@ public static void TestAddTake_Longrunning(int numOfAdds, int numOfTakes, int bo
/// present in the collection.</summary>
/// <param name="numOfThreads">Number of producer threads.</param>
/// <param name="numOfElementsPerThread">Number of elements added per thread.</param>
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Theory]
[InlineData(2, 1024)]
[InlineData(8, 512)]
public static void TestConcurrentAdd(int numOfThreads, int numOfElementsPerThread)
Expand Down Expand Up @@ -291,7 +292,7 @@ public static void TestConcurrentAdd(int numOfThreads, int numOfElementsPerThrea
/// are consumed by consumers with no element lost nor consumed more than once.</summary>
/// <param name="threads">Total number of producer and consumer threads.</param>
/// <param name="numOfElementsPerThread">Number of elements to Add/Take per thread.</param>
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Theory]
[InlineData(8, 1024)]
public static void TestConcurrentAddTake(int numOfThreads, int numOfElementsPerThread)
{
Expand Down Expand Up @@ -534,7 +535,7 @@ public static void Test7_CompleteAdding()
Assert.Equal(0, counter);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Fact]
public static void Test7_ConcurrentAdd_CompleteAdding()
{
BlockingCollection<ushort> blockingCollection = ConstructBlockingCollection<ushort>();
Expand Down Expand Up @@ -741,7 +742,7 @@ public static void TestAddAnyTakeAny_Longrunning(int numOfAdds, int numOfTakes,
/// are consumed by consumers with no element lost nor consumed more than once.</summary>
/// <param name="threads">Total number of producer and consumer threads.</param>
/// <param name="numOfElementsPerThread">Number of elements to Add/Take per thread.</param>
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
[Theory]
[InlineData(4, 2048, 2, 64)]
[OuterLoop]
private static void TestConcurrentAddAnyTakeAny(int numOfThreads, int numOfElementsPerThread, int numOfCollections, int boundOfCollections)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
<FeatureWasmManagedThreads Condition="'$(TargetPlatformIdentifier)' == 'browser' and '$(WasmEnableThreads)' == 'true'">true</FeatureWasmManagedThreads>
<DefineConstants Condition="'$(FeatureWasmManagedThreads)' == 'true'" >$(DefineConstants);FEATURE_WASM_MANAGED_THREADS</DefineConstants>
<FeatureSingleThread Condition="('$(TargetsBrowser)' == 'true' or '$(TargetsWasi)' == 'true') and '$(WasmEnableThreads)' != 'true'">true</FeatureSingleThread>
<DefineConstants Condition="'$(FeatureSingleThread)' == 'true'">$(DefineConstants);FEATURE_SINGLE_THREADED</DefineConstants>
</PropertyGroup>

<!-- Compiled Source Files -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Parallel;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -64,9 +65,11 @@ public static class ParallelEnumerable

// When running in single partition mode, PLINQ operations will occur on a single partition and will not
// be executed in parallel, but will retain PLINQ semantics (exceptions wrapped as aggregates, etc).
#if !FEATURE_WASM_MANAGED_THREADS
[System.Runtime.Versioning.SupportedOSPlatformGuard("browser")]
internal static bool SinglePartitionMode => OperatingSystem.IsBrowser() || OperatingSystem.IsWasi();

[SupportedOSPlatformGuard("browser")]
[SupportedOSPlatformGuard("wasi")]
#if FEATURE_SINGLE_THREADED
internal static bool SinglePartitionMode => true;
#else
internal static bool SinglePartitionMode => false;
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public async Task ReceiveHelloWithContextTakeover()
Assert.Equal("Hello", Encoding.UTF8.GetString(buffer.Span));
}

[Fact]
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public async Task SendHelloWithContextTakeover()
{
WebSocketTestStream stream = new();
Expand Down Expand Up @@ -164,7 +164,7 @@ public async Task ReceiveHelloWithoutContextTakeover()
}
}

[Fact]
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public async Task SendHelloWithoutContextTakeover()
{
WebSocketTestStream stream = new();
Expand Down
10 changes: 5 additions & 5 deletions src/libraries/System.Private.CoreLib/src/System/Environment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ public readonly struct ProcessCpuUsage
public TimeSpan TotalTime => UserTime + PrivilegedTime;
}

public static int ProcessorCount { get; } = GetProcessorCount();

/// <summary>
/// Gets whether the current machine has only a single processor.
/// </summary>
#if !FEATURE_SINGLE_THREADED
internal static bool IsSingleProcessor => ProcessorCount == 1;
#else
#if FEATURE_SINGLE_THREADED
internal const bool IsSingleProcessor = true;
public static int ProcessorCount => 1;
#else
internal static bool IsSingleProcessor => ProcessorCount == 1;
public static int ProcessorCount { get; } = GetProcessorCount();
#endif
private static volatile sbyte s_privilegedProcess;

Expand Down
14 changes: 8 additions & 6 deletions src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,16 @@ internal Task<int> BeginReadInternal(
// thread if it does a second IO request until the first one completes.
SemaphoreSlim semaphore = EnsureAsyncActiveSemaphoreInitialized();
Task? semaphoreTask = null;
if (serializeAsynchronously)

// The synchronous path is emulating legacy behavior.
// Drop the emulation for IsSingleThreaded to avoid throwing.
if (Thread.IsSingleThreaded || serializeAsynchronously)
{
semaphoreTask = semaphore.WaitAsync();
}
else
{
#pragma warning disable CA1416 // Validate platform compatibility, issue: https://github.com/dotnet/runtime/issues/44543
semaphore.Wait();
#pragma warning restore CA1416
}

// Create the task to asynchronously do a Read. This task serves both
Expand Down Expand Up @@ -490,15 +491,16 @@ internal Task BeginWriteInternal(
// thread if it does a second IO request until the first one completes.
SemaphoreSlim semaphore = EnsureAsyncActiveSemaphoreInitialized();
Task? semaphoreTask = null;
if (serializeAsynchronously)

// The synchronous path is emulating legacy behavior.
// Drop the emulation for IsSingleThreaded to avoid throwing.
if (Thread.IsSingleThreaded || serializeAsynchronously)
{
semaphoreTask = semaphore.WaitAsync(); // kick off the asynchronous wait, but don't block
}
else
{
#pragma warning disable CA1416 // Validate platform compatibility, issue: https://github.com/dotnet/runtime/issues/44543
semaphore.Wait(); // synchronously wait here
#pragma warning restore CA1416
}

// Create the task to asynchronously do a Write. This task serves both
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -883,11 +883,9 @@ public static TextWriter Synchronized(TextWriter writer)
{
ArgumentNullException.ThrowIfNull(writer);

#if (!TARGET_BROWSER && !TARGET_WASI) || FEATURE_WASM_MANAGED_THREADS
return writer is SyncTextWriter ? writer : new SyncTextWriter(writer);
#else
return writer;
#endif
return Thread.IsSingleThreaded || writer is SyncTextWriter
? writer
: new SyncTextWriter(writer);
}

internal sealed class SyncTextWriter : TextWriter, IDisposable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ internal static void ResetThreadPoolThread(Thread currentThread)
[Conditional("DEBUG")]
internal static void CheckThreadPoolAndContextsAreDefault()
{
Debug.Assert(!Thread.IsThreadStartSupported || Thread.CurrentThread.IsThreadPoolThread); // there are no dedicated threadpool threads on runtimes where we can't start threads
Debug.Assert(Thread.IsSingleThreaded || Thread.CurrentThread.IsThreadPoolThread); // there are no dedicated threadpool threads on runtimes where we can't start threads
Debug.Assert(Thread.CurrentThread._executionContext == null, "ThreadPool thread not on Default ExecutionContext.");
Debug.Assert(Thread.CurrentThread._synchronizationContext == null, "ThreadPool thread not on Default SynchronizationContext.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ internal int TryEnterSlow(int timeoutMs, int currentThreadId)
goto Locked;
}

Thread.ThrowIfSingleThreaded();

// Lock was not acquired and a waiter was registered. All following paths need to unregister the waiter, including
// exceptional paths.
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ public bool Wait(int timeoutMs)
{
Debug.Assert(timeoutMs >= -1);

#if FEATURE_WASM_MANAGED_THREADS
Thread.AssureBlockingPossible();
#endif

// Try one-shot acquire first
Counts counts = _separated._counts;
if (counts.SignalCount != 0)
Expand All @@ -55,6 +51,8 @@ public bool Wait(int timeoutMs)
}
}

Thread.ThrowIfSingleThreaded();

return WaitSlow(timeoutMs);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ private void WaitAndAcquire()
{
VerifyIsNotLocked();

Thread.ThrowIfSingleThreaded();

// Spin a bit to see if the lock becomes available, before forcing the thread into a wait state
if (_spinWaiter.SpinWaitForCondition(s_spinWaitTryAcquireCallback, this, SpinCount, SpinSleep0Threshold))
{
Expand Down
Loading
Loading