From b22e759ef9c1fe1ef689b70a388c161e273d124f Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 20 Mar 2024 14:51:10 +0100 Subject: [PATCH] step one --- .../ref/System.Private.CoreLib.ExtraApis.cs | 2 + .../ref/System.Private.CoreLib.ExtraApis.txt | 1 + .../src/System/Threading/Thread.cs | 22 +- ...tem.Runtime.InteropServices.JavaScript.sln | 389 +++++++++--------- .../JavaScript/Interop/JavaScriptExports.cs | 71 ++-- .../JavaScript/JSFunctionBinding.cs | 26 +- .../JavaScript/JSHostImplementation.Types.cs | 36 +- .../JavaScript/JSProxyContext.cs | 6 +- .../JavaScript/JSSynchronizationContext.cs | 13 +- .../JavaScript/WebWorkerTest.Http.cs | 6 +- .../JavaScript/WebWorkerTest.cs | 53 ++- .../JavaScript/WebWorkerTestBase.cs | 70 +++- .../JavaScript/WebWorkerTestHelper.cs | 6 +- .../CompatibilitySuppressions.Threading.xml | 4 + src/mono/browser/runtime/corebindings.c | 2 + src/mono/browser/runtime/exports-binding.ts | 4 +- src/mono/browser/runtime/interp-pgo.ts | 2 - src/mono/browser/runtime/invoke-js.ts | 13 +- src/mono/browser/runtime/loader/config.ts | 37 +- src/mono/browser/runtime/managed-exports.ts | 36 +- src/mono/browser/runtime/multi-threading.md | 52 --- src/mono/browser/runtime/pthreads/index.ts | 8 + src/mono/browser/runtime/startup.ts | 20 +- src/mono/browser/runtime/types/internal.ts | 63 ++- src/mono/browser/test-main.js | 3 +- src/mono/mono/utils/mono-threads-wasm.c | 1 - src/mono/sample/wasm/browser-threads/main.js | 3 + 27 files changed, 469 insertions(+), 480 deletions(-) delete mode 100644 src/mono/browser/runtime/multi-threading.md diff --git a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.cs b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.cs index b16548c7b4c374..45a5b9f0372696 100644 --- a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.cs +++ b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.cs @@ -45,6 +45,8 @@ public partial class Thread { [ThreadStatic] public static bool ThrowOnBlockingWaitOnJSInteropThread; + [ThreadStatic] + public static bool WarnOnBlockingWaitOnJSInteropThread; public static void AssureBlockingPossible() { throw null; } public static void ForceBlockingWait(Action action, object? state) { throw null; } diff --git a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.txt b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.txt index 3b80cb0de6753b..2a6434973ff1e3 100644 --- a/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.txt +++ b/src/libraries/System.Private.CoreLib/ref/System.Private.CoreLib.ExtraApis.txt @@ -7,4 +7,5 @@ T:System.Diagnostics.DebugProvider M:System.Diagnostics.Debug.SetProvider(System.Diagnostics.DebugProvider) M:System.Threading.Thread.AssureBlockingPossible F:System.Threading.Thread.ThrowOnBlockingWaitOnJSInteropThread +F:System.Threading.Thread.WarnOnBlockingWaitOnJSInteropThread F:System.Threading.Thread.ForceBlockingWait diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs index 9d3fd7a0466d72..3ef77076a01988 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs @@ -729,26 +729,46 @@ public static int GetCurrentProcessorId() [ThreadStatic] public static bool ThrowOnBlockingWaitOnJSInteropThread; - public static void AssureBlockingPossible() + [ThreadStatic] + public static bool WarnOnBlockingWaitOnJSInteropThread; + +#pragma warning disable CS3001 + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern unsafe void WarnAboutBlockingWait(char* stack, int length); + + public static unsafe void AssureBlockingPossible() { if (ThrowOnBlockingWaitOnJSInteropThread) { throw new PlatformNotSupportedException(SR.WasmThreads_BlockingWaitNotSupportedOnJSInterop); } + else if (WarnOnBlockingWaitOnJSInteropThread) + { + var st = $"Blocking the thread with JS interop is dangerous and could lead to deadlock. ManagedThreadId: {Environment.CurrentManagedThreadId}\n{Environment.StackTrace}"; + fixed (char* stack = st) + { + WarnAboutBlockingWait(stack, st.Length); + } + } } +#pragma warning restore CS3001 + public static void ForceBlockingWait(Action action, object? state = null) { var flag = ThrowOnBlockingWaitOnJSInteropThread; + var wflag = WarnOnBlockingWaitOnJSInteropThread; try { ThrowOnBlockingWaitOnJSInteropThread = false; + WarnOnBlockingWaitOnJSInteropThread = false; action(state); } finally { ThrowOnBlockingWaitOnJSInteropThread = flag; + WarnOnBlockingWaitOnJSInteropThread = wflag; } } #endif diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln index ef751e9c516574..8a16737cdda701 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34414.90 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{0F7BA062-C34C-41A8-840F-F0B074B18686}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}" @@ -71,16 +75,21 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{32CDDDCD-531 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{39B30F44-B141-44E9-B7A7-B1A9EDB1A61C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "tools\gen", "{1A04C5D7-1DE9-47C3-BCC1-147678B9085F}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{1A04C5D7-1DE9-47C3-BCC1-147678B9085F}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "tools\src", "{32733782-56D6-4EAF-B94E-5D10C759DD57}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{32733782-56D6-4EAF-B94E-5D10C759DD57}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "tools\ref", "{19EA33B4-0E87-451F-95E3-8F3959117654}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{19EA33B4-0E87-451F-95E3-8F3959117654}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{7392B838-42AF-4F54-AD02-366397DAF640}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|arm = Checked|arm + Checked|arm64 = Checked|arm64 + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|arm = Debug|arm Debug|arm64 = Debug|arm64 @@ -91,13 +100,18 @@ Global Release|arm64 = Release|arm64 Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|arm = Checked|arm - Checked|arm64 = Checked|arm64 - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.ActiveCfg = Checked|x64 + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.Build.0 = Checked|x64 + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.ActiveCfg = Checked|arm + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.Build.0 = Checked|arm + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.ActiveCfg = Checked|arm64 + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.Build.0 = Checked|arm64 + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.ActiveCfg = Checked|x64 + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.Build.0 = Checked|x64 + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.ActiveCfg = Checked|x86 + {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.Build.0 = Checked|x86 {0F7BA062-C34C-41A8-840F-F0B074B18686}.Debug|Any CPU.ActiveCfg = Debug|x64 {0F7BA062-C34C-41A8-840F-F0B074B18686}.Debug|Any CPU.Build.0 = Debug|x64 {0F7BA062-C34C-41A8-840F-F0B074B18686}.Debug|arm.ActiveCfg = Debug|arm @@ -118,16 +132,11 @@ Global {0F7BA062-C34C-41A8-840F-F0B074B18686}.Release|x64.Build.0 = Release|x64 {0F7BA062-C34C-41A8-840F-F0B074B18686}.Release|x86.ActiveCfg = Release|x86 {0F7BA062-C34C-41A8-840F-F0B074B18686}.Release|x86.Build.0 = Release|x86 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.ActiveCfg = Checked|x64 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|Any CPU.Build.0 = Checked|x64 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.ActiveCfg = Checked|arm - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm.Build.0 = Checked|arm - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.ActiveCfg = Checked|arm64 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|arm64.Build.0 = Checked|arm64 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.ActiveCfg = Checked|x64 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x64.Build.0 = Checked|x64 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.ActiveCfg = Checked|x86 - {0F7BA062-C34C-41A8-840F-F0B074B18686}.Checked|x86.Build.0 = Checked|x86 + {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm.ActiveCfg = Debug|Any CPU + {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm64.ActiveCfg = Debug|Any CPU + {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x64.ActiveCfg = Debug|Any CPU + {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x86.ActiveCfg = Debug|Any CPU {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Debug|Any CPU.Build.0 = Debug|Any CPU {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -144,11 +153,11 @@ Global {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Release|x64.Build.0 = Release|Any CPU {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Release|x86.ActiveCfg = Release|Any CPU {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Release|x86.Build.0 = Release|Any CPU - {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm.ActiveCfg = Debug|Any CPU - {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|arm64.ActiveCfg = Debug|Any CPU - {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x64.ActiveCfg = Debug|Any CPU - {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272}.Checked|x86.ActiveCfg = Debug|Any CPU + {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|arm.ActiveCfg = Debug|Any CPU + {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|arm64.ActiveCfg = Debug|Any CPU + {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|x64.ActiveCfg = Debug|Any CPU + {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|x86.ActiveCfg = Debug|Any CPU {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -165,11 +174,11 @@ Global {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Release|x64.Build.0 = Release|Any CPU {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Release|x86.ActiveCfg = Release|Any CPU {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Release|x86.Build.0 = Release|Any CPU - {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|arm.ActiveCfg = Debug|Any CPU - {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|arm64.ActiveCfg = Debug|Any CPU - {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|x64.ActiveCfg = Debug|Any CPU - {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2}.Checked|x86.ActiveCfg = Debug|Any CPU + {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm.ActiveCfg = Debug|Any CPU + {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm64.ActiveCfg = Debug|Any CPU + {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x64.ActiveCfg = Debug|Any CPU + {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x86.ActiveCfg = Debug|Any CPU {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Debug|Any CPU.Build.0 = Debug|Any CPU {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -186,11 +195,11 @@ Global {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Release|x64.Build.0 = Release|Any CPU {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Release|x86.ActiveCfg = Release|Any CPU {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Release|x86.Build.0 = Release|Any CPU - {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm.ActiveCfg = Debug|Any CPU - {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|arm64.ActiveCfg = Debug|Any CPU - {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x64.ActiveCfg = Debug|Any CPU - {FC1007CC-9E52-49B7-A47B-A8AE76E75986}.Checked|x86.ActiveCfg = Debug|Any CPU + {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm.ActiveCfg = Debug|Any CPU + {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm64.ActiveCfg = Debug|Any CPU + {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x64.ActiveCfg = Debug|Any CPU + {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x86.ActiveCfg = Debug|Any CPU {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -207,11 +216,11 @@ Global {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Release|x64.Build.0 = Release|Any CPU {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Release|x86.ActiveCfg = Release|Any CPU {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Release|x86.Build.0 = Release|Any CPU - {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm.ActiveCfg = Debug|Any CPU - {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|arm64.ActiveCfg = Debug|Any CPU - {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x64.ActiveCfg = Debug|Any CPU - {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3}.Checked|x86.ActiveCfg = Debug|Any CPU + {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm.ActiveCfg = Debug|Any CPU + {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm64.ActiveCfg = Debug|Any CPU + {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x64.ActiveCfg = Debug|Any CPU + {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x86.ActiveCfg = Debug|Any CPU {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Debug|Any CPU.Build.0 = Debug|Any CPU {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -228,11 +237,11 @@ Global {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Release|x64.Build.0 = Release|Any CPU {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Release|x86.ActiveCfg = Release|Any CPU {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Release|x86.Build.0 = Release|Any CPU - {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm.ActiveCfg = Debug|Any CPU - {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|arm64.ActiveCfg = Debug|Any CPU - {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x64.ActiveCfg = Debug|Any CPU - {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB}.Checked|x86.ActiveCfg = Debug|Any CPU + {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm.ActiveCfg = Debug|Any CPU + {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm64.ActiveCfg = Debug|Any CPU + {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x64.ActiveCfg = Debug|Any CPU + {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x86.ActiveCfg = Debug|Any CPU {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -249,11 +258,11 @@ Global {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Release|x64.Build.0 = Release|Any CPU {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Release|x86.ActiveCfg = Release|Any CPU {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Release|x86.Build.0 = Release|Any CPU - {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm.ActiveCfg = Debug|Any CPU - {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|arm64.ActiveCfg = Debug|Any CPU - {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x64.ActiveCfg = Debug|Any CPU - {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8}.Checked|x86.ActiveCfg = Debug|Any CPU + {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm.ActiveCfg = Debug|Any CPU + {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm64.ActiveCfg = Debug|Any CPU + {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x64.ActiveCfg = Debug|Any CPU + {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x86.ActiveCfg = Debug|Any CPU {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Debug|Any CPU.Build.0 = Debug|Any CPU {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -270,11 +279,11 @@ Global {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Release|x64.Build.0 = Release|Any CPU {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Release|x86.ActiveCfg = Release|Any CPU {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Release|x86.Build.0 = Release|Any CPU - {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm.ActiveCfg = Debug|Any CPU - {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|arm64.ActiveCfg = Debug|Any CPU - {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x64.ActiveCfg = Debug|Any CPU - {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE}.Checked|x86.ActiveCfg = Debug|Any CPU + {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm.ActiveCfg = Debug|Any CPU + {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm64.ActiveCfg = Debug|Any CPU + {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x64.ActiveCfg = Debug|Any CPU + {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x86.ActiveCfg = Debug|Any CPU {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Debug|Any CPU.Build.0 = Debug|Any CPU {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -291,11 +300,11 @@ Global {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Release|x64.Build.0 = Release|Any CPU {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Release|x86.ActiveCfg = Release|Any CPU {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Release|x86.Build.0 = Release|Any CPU - {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm.ActiveCfg = Debug|Any CPU - {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|arm64.ActiveCfg = Debug|Any CPU - {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x64.ActiveCfg = Debug|Any CPU - {8CFB1155-26A2-43E3-B192-1F87D9E543AC}.Checked|x86.ActiveCfg = Debug|Any CPU + {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm.ActiveCfg = Debug|Any CPU + {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm64.ActiveCfg = Debug|Any CPU + {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x64.ActiveCfg = Debug|Any CPU + {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x86.ActiveCfg = Debug|Any CPU {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Debug|Any CPU.Build.0 = Debug|Any CPU {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -312,11 +321,11 @@ Global {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Release|x64.Build.0 = Release|Any CPU {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Release|x86.ActiveCfg = Release|Any CPU {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Release|x86.Build.0 = Release|Any CPU - {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm.ActiveCfg = Debug|Any CPU - {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|arm64.ActiveCfg = Debug|Any CPU - {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x64.ActiveCfg = Debug|Any CPU - {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08}.Checked|x86.ActiveCfg = Debug|Any CPU + {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm.ActiveCfg = Debug|Any CPU + {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm64.ActiveCfg = Debug|Any CPU + {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x64.ActiveCfg = Debug|Any CPU + {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x86.ActiveCfg = Debug|Any CPU {74143A5F-6987-4AB5-B786-DE358F01241B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {74143A5F-6987-4AB5-B786-DE358F01241B}.Debug|Any CPU.Build.0 = Debug|Any CPU {74143A5F-6987-4AB5-B786-DE358F01241B}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -333,11 +342,11 @@ Global {74143A5F-6987-4AB5-B786-DE358F01241B}.Release|x64.Build.0 = Release|Any CPU {74143A5F-6987-4AB5-B786-DE358F01241B}.Release|x86.ActiveCfg = Release|Any CPU {74143A5F-6987-4AB5-B786-DE358F01241B}.Release|x86.Build.0 = Release|Any CPU - {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm.ActiveCfg = Debug|Any CPU - {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|arm64.ActiveCfg = Debug|Any CPU - {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x64.ActiveCfg = Debug|Any CPU - {74143A5F-6987-4AB5-B786-DE358F01241B}.Checked|x86.ActiveCfg = Debug|Any CPU + {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm.ActiveCfg = Debug|Any CPU + {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm64.ActiveCfg = Debug|Any CPU + {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x64.ActiveCfg = Debug|Any CPU + {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x86.ActiveCfg = Debug|Any CPU {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -354,11 +363,11 @@ Global {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Release|x64.Build.0 = Release|Any CPU {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Release|x86.ActiveCfg = Release|Any CPU {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Release|x86.Build.0 = Release|Any CPU - {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm.ActiveCfg = Debug|Any CPU - {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|arm64.ActiveCfg = Debug|Any CPU - {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x64.ActiveCfg = Debug|Any CPU - {CE5E53C1-F9B5-41EE-8D00-837913EC57D1}.Checked|x86.ActiveCfg = Debug|Any CPU + {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm.ActiveCfg = Debug|Any CPU + {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm64.ActiveCfg = Debug|Any CPU + {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x64.ActiveCfg = Debug|Any CPU + {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x86.ActiveCfg = Debug|Any CPU {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Debug|Any CPU.Build.0 = Debug|Any CPU {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -375,11 +384,11 @@ Global {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Release|x64.Build.0 = Release|Any CPU {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Release|x86.ActiveCfg = Release|Any CPU {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Release|x86.Build.0 = Release|Any CPU - {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm.ActiveCfg = Debug|Any CPU - {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|arm64.ActiveCfg = Debug|Any CPU - {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x64.ActiveCfg = Debug|Any CPU - {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1}.Checked|x86.ActiveCfg = Debug|Any CPU + {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm.ActiveCfg = Debug|Any CPU + {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm64.ActiveCfg = Debug|Any CPU + {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x64.ActiveCfg = Debug|Any CPU + {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x86.ActiveCfg = Debug|Any CPU {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Debug|Any CPU.Build.0 = Debug|Any CPU {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -396,11 +405,11 @@ Global {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Release|x64.Build.0 = Release|Any CPU {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Release|x86.ActiveCfg = Release|Any CPU {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Release|x86.Build.0 = Release|Any CPU - {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm.ActiveCfg = Debug|Any CPU - {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|arm64.ActiveCfg = Debug|Any CPU - {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x64.ActiveCfg = Debug|Any CPU - {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45}.Checked|x86.ActiveCfg = Debug|Any CPU + {BFED925C-18F2-4C98-833E-66F205234598}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm.ActiveCfg = Debug|Any CPU + {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm64.ActiveCfg = Debug|Any CPU + {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x64.ActiveCfg = Debug|Any CPU + {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x86.ActiveCfg = Debug|Any CPU {BFED925C-18F2-4C98-833E-66F205234598}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BFED925C-18F2-4C98-833E-66F205234598}.Debug|Any CPU.Build.0 = Debug|Any CPU {BFED925C-18F2-4C98-833E-66F205234598}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -417,11 +426,11 @@ Global {BFED925C-18F2-4C98-833E-66F205234598}.Release|x64.Build.0 = Release|Any CPU {BFED925C-18F2-4C98-833E-66F205234598}.Release|x86.ActiveCfg = Release|Any CPU {BFED925C-18F2-4C98-833E-66F205234598}.Release|x86.Build.0 = Release|Any CPU - {BFED925C-18F2-4C98-833E-66F205234598}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm.ActiveCfg = Debug|Any CPU - {BFED925C-18F2-4C98-833E-66F205234598}.Checked|arm64.ActiveCfg = Debug|Any CPU - {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x64.ActiveCfg = Debug|Any CPU - {BFED925C-18F2-4C98-833E-66F205234598}.Checked|x86.ActiveCfg = Debug|Any CPU + {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm.ActiveCfg = Debug|Any CPU + {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm64.ActiveCfg = Debug|Any CPU + {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x64.ActiveCfg = Debug|Any CPU + {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x86.ActiveCfg = Debug|Any CPU {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Debug|Any CPU.Build.0 = Debug|Any CPU {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -438,11 +447,11 @@ Global {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Release|x64.Build.0 = Release|Any CPU {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Release|x86.ActiveCfg = Release|Any CPU {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Release|x86.Build.0 = Release|Any CPU - {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm.ActiveCfg = Debug|Any CPU - {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|arm64.ActiveCfg = Debug|Any CPU - {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x64.ActiveCfg = Debug|Any CPU - {765B4AA5-723A-44FF-BC4E-EB0F03103F6D}.Checked|x86.ActiveCfg = Debug|Any CPU + {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm.ActiveCfg = Debug|Any CPU + {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm64.ActiveCfg = Debug|Any CPU + {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x64.ActiveCfg = Debug|Any CPU + {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x86.ActiveCfg = Debug|Any CPU {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Debug|Any CPU.Build.0 = Debug|Any CPU {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -459,11 +468,11 @@ Global {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Release|x64.Build.0 = Release|Any CPU {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Release|x86.ActiveCfg = Release|Any CPU {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Release|x86.Build.0 = Release|Any CPU - {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm.ActiveCfg = Debug|Any CPU - {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|arm64.ActiveCfg = Debug|Any CPU - {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x64.ActiveCfg = Debug|Any CPU - {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD}.Checked|x86.ActiveCfg = Debug|Any CPU + {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm.ActiveCfg = Debug|Any CPU + {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm64.ActiveCfg = Debug|Any CPU + {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x64.ActiveCfg = Debug|Any CPU + {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x86.ActiveCfg = Debug|Any CPU {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Debug|Any CPU.Build.0 = Debug|Any CPU {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -480,11 +489,11 @@ Global {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Release|x64.Build.0 = Release|Any CPU {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Release|x86.ActiveCfg = Release|Any CPU {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Release|x86.Build.0 = Release|Any CPU - {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm.ActiveCfg = Debug|Any CPU - {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|arm64.ActiveCfg = Debug|Any CPU - {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x64.ActiveCfg = Debug|Any CPU - {B4E3E774-2C16-4CBF-87EF-88C547529B94}.Checked|x86.ActiveCfg = Debug|Any CPU + {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm.ActiveCfg = Debug|Any CPU + {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm64.ActiveCfg = Debug|Any CPU + {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x64.ActiveCfg = Debug|Any CPU + {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x86.ActiveCfg = Debug|Any CPU {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Debug|Any CPU.Build.0 = Debug|Any CPU {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -501,11 +510,11 @@ Global {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Release|x64.Build.0 = Release|Any CPU {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Release|x86.ActiveCfg = Release|Any CPU {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Release|x86.Build.0 = Release|Any CPU - {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm.ActiveCfg = Debug|Any CPU - {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|arm64.ActiveCfg = Debug|Any CPU - {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x64.ActiveCfg = Debug|Any CPU - {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532}.Checked|x86.ActiveCfg = Debug|Any CPU + {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm.ActiveCfg = Debug|Any CPU + {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm64.ActiveCfg = Debug|Any CPU + {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x64.ActiveCfg = Debug|Any CPU + {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x86.ActiveCfg = Debug|Any CPU {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Debug|Any CPU.Build.0 = Debug|Any CPU {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -522,11 +531,11 @@ Global {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Release|x64.Build.0 = Release|Any CPU {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Release|x86.ActiveCfg = Release|Any CPU {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Release|x86.Build.0 = Release|Any CPU - {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm.ActiveCfg = Debug|Any CPU - {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|arm64.ActiveCfg = Debug|Any CPU - {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x64.ActiveCfg = Debug|Any CPU - {44BAE6F1-94C2-415B-9A16-3B8EC429B09B}.Checked|x86.ActiveCfg = Debug|Any CPU + {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm.ActiveCfg = Debug|Any CPU + {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm64.ActiveCfg = Debug|Any CPU + {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x64.ActiveCfg = Debug|Any CPU + {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x86.ActiveCfg = Debug|Any CPU {1EB2EBE2-12EA-4545-B390-098F083329A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1EB2EBE2-12EA-4545-B390-098F083329A1}.Debug|Any CPU.Build.0 = Debug|Any CPU {1EB2EBE2-12EA-4545-B390-098F083329A1}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -543,11 +552,11 @@ Global {1EB2EBE2-12EA-4545-B390-098F083329A1}.Release|x64.Build.0 = Release|Any CPU {1EB2EBE2-12EA-4545-B390-098F083329A1}.Release|x86.ActiveCfg = Release|Any CPU {1EB2EBE2-12EA-4545-B390-098F083329A1}.Release|x86.Build.0 = Release|Any CPU - {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm.ActiveCfg = Debug|Any CPU - {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|arm64.ActiveCfg = Debug|Any CPU - {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x64.ActiveCfg = Debug|Any CPU - {1EB2EBE2-12EA-4545-B390-098F083329A1}.Checked|x86.ActiveCfg = Debug|Any CPU + {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm.ActiveCfg = Debug|Any CPU + {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm64.ActiveCfg = Debug|Any CPU + {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x64.ActiveCfg = Debug|Any CPU + {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x86.ActiveCfg = Debug|Any CPU {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Debug|Any CPU.Build.0 = Debug|Any CPU {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -564,11 +573,11 @@ Global {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Release|x64.Build.0 = Release|Any CPU {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Release|x86.ActiveCfg = Release|Any CPU {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Release|x86.Build.0 = Release|Any CPU - {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm.ActiveCfg = Debug|Any CPU - {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|arm64.ActiveCfg = Debug|Any CPU - {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x64.ActiveCfg = Debug|Any CPU - {B18C5A3A-CAB0-4B62-9C01-7A046E05089F}.Checked|x86.ActiveCfg = Debug|Any CPU + {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm.ActiveCfg = Debug|Any CPU + {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm64.ActiveCfg = Debug|Any CPU + {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x64.ActiveCfg = Debug|Any CPU + {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x86.ActiveCfg = Debug|Any CPU {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Debug|Any CPU.Build.0 = Debug|Any CPU {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -585,11 +594,11 @@ Global {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Release|x64.Build.0 = Release|Any CPU {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Release|x86.ActiveCfg = Release|Any CPU {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Release|x86.Build.0 = Release|Any CPU - {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm.ActiveCfg = Debug|Any CPU - {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|arm64.ActiveCfg = Debug|Any CPU - {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x64.ActiveCfg = Debug|Any CPU - {04A40E6C-DD10-473D-AFF8-9033E936DC46}.Checked|x86.ActiveCfg = Debug|Any CPU + {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm.ActiveCfg = Debug|Any CPU + {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm64.ActiveCfg = Debug|Any CPU + {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x64.ActiveCfg = Debug|Any CPU + {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x86.ActiveCfg = Debug|Any CPU {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Debug|Any CPU.Build.0 = Debug|Any CPU {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -606,11 +615,11 @@ Global {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Release|x64.Build.0 = Release|Any CPU {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Release|x86.ActiveCfg = Release|Any CPU {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Release|x86.Build.0 = Release|Any CPU - {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm.ActiveCfg = Debug|Any CPU - {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|arm64.ActiveCfg = Debug|Any CPU - {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x64.ActiveCfg = Debug|Any CPU - {B86E4599-88CF-4662-96BA-3FCB926D0BA1}.Checked|x86.ActiveCfg = Debug|Any CPU + {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm.ActiveCfg = Debug|Any CPU + {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm64.ActiveCfg = Debug|Any CPU + {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x64.ActiveCfg = Debug|Any CPU + {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x86.ActiveCfg = Debug|Any CPU {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Debug|Any CPU.Build.0 = Debug|Any CPU {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -627,11 +636,11 @@ Global {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Release|x64.Build.0 = Release|Any CPU {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Release|x86.ActiveCfg = Release|Any CPU {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Release|x86.Build.0 = Release|Any CPU - {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm.ActiveCfg = Debug|Any CPU - {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|arm64.ActiveCfg = Debug|Any CPU - {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x64.ActiveCfg = Debug|Any CPU - {424A7718-F5B7-41FB-A74B-1E23A9BF13EA}.Checked|x86.ActiveCfg = Debug|Any CPU + {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm.ActiveCfg = Debug|Any CPU + {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm64.ActiveCfg = Debug|Any CPU + {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x64.ActiveCfg = Debug|Any CPU + {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x86.ActiveCfg = Debug|Any CPU {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -648,11 +657,11 @@ Global {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Release|x64.Build.0 = Release|Any CPU {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Release|x86.ActiveCfg = Release|Any CPU {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Release|x86.Build.0 = Release|Any CPU - {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm.ActiveCfg = Debug|Any CPU - {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|arm64.ActiveCfg = Debug|Any CPU - {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x64.ActiveCfg = Debug|Any CPU - {D620CBA3-326B-4E4A-81C2-3D9E9258E45C}.Checked|x86.ActiveCfg = Debug|Any CPU + {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm.ActiveCfg = Debug|Any CPU + {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm64.ActiveCfg = Debug|Any CPU + {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x64.ActiveCfg = Debug|Any CPU + {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x86.ActiveCfg = Debug|Any CPU {8683B814-5459-4412-A881-ECAFF9ED1781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8683B814-5459-4412-A881-ECAFF9ED1781}.Debug|Any CPU.Build.0 = Debug|Any CPU {8683B814-5459-4412-A881-ECAFF9ED1781}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -669,11 +678,11 @@ Global {8683B814-5459-4412-A881-ECAFF9ED1781}.Release|x64.Build.0 = Release|Any CPU {8683B814-5459-4412-A881-ECAFF9ED1781}.Release|x86.ActiveCfg = Release|Any CPU {8683B814-5459-4412-A881-ECAFF9ED1781}.Release|x86.Build.0 = Release|Any CPU - {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm.ActiveCfg = Debug|Any CPU - {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|arm64.ActiveCfg = Debug|Any CPU - {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x64.ActiveCfg = Debug|Any CPU - {8683B814-5459-4412-A881-ECAFF9ED1781}.Checked|x86.ActiveCfg = Debug|Any CPU + {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm.ActiveCfg = Debug|Any CPU + {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm64.ActiveCfg = Debug|Any CPU + {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x64.ActiveCfg = Debug|Any CPU + {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x86.ActiveCfg = Debug|Any CPU {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Debug|Any CPU.Build.0 = Debug|Any CPU {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -690,11 +699,11 @@ Global {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Release|x64.Build.0 = Release|Any CPU {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Release|x86.ActiveCfg = Release|Any CPU {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Release|x86.Build.0 = Release|Any CPU - {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm.ActiveCfg = Debug|Any CPU - {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|arm64.ActiveCfg = Debug|Any CPU - {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x64.ActiveCfg = Debug|Any CPU - {4D8B7538-D933-4F3A-818D-4E19ABA7E182}.Checked|x86.ActiveCfg = Debug|Any CPU + {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm.ActiveCfg = Debug|Any CPU + {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm64.ActiveCfg = Debug|Any CPU + {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x64.ActiveCfg = Debug|Any CPU + {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x86.ActiveCfg = Debug|Any CPU {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -711,11 +720,11 @@ Global {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Release|x64.Build.0 = Release|Any CPU {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Release|x86.ActiveCfg = Release|Any CPU {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Release|x86.Build.0 = Release|Any CPU - {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm.ActiveCfg = Debug|Any CPU - {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|arm64.ActiveCfg = Debug|Any CPU - {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x64.ActiveCfg = Debug|Any CPU - {6C60944F-4FE1-450F-884B-D523EDFCFAB3}.Checked|x86.ActiveCfg = Debug|Any CPU + {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm.ActiveCfg = Debug|Any CPU + {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm64.ActiveCfg = Debug|Any CPU + {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x64.ActiveCfg = Debug|Any CPU + {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x86.ActiveCfg = Debug|Any CPU {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -732,11 +741,11 @@ Global {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Release|x64.Build.0 = Release|Any CPU {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Release|x86.ActiveCfg = Release|Any CPU {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Release|x86.Build.0 = Release|Any CPU - {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm.ActiveCfg = Debug|Any CPU - {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|arm64.ActiveCfg = Debug|Any CPU - {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x64.ActiveCfg = Debug|Any CPU - {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B}.Checked|x86.ActiveCfg = Debug|Any CPU + {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm.ActiveCfg = Debug|Any CPU + {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm64.ActiveCfg = Debug|Any CPU + {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x64.ActiveCfg = Debug|Any CPU + {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x86.ActiveCfg = Debug|Any CPU {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Debug|Any CPU.Build.0 = Debug|Any CPU {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -753,11 +762,11 @@ Global {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Release|x64.Build.0 = Release|Any CPU {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Release|x86.ActiveCfg = Release|Any CPU {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Release|x86.Build.0 = Release|Any CPU - {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm.ActiveCfg = Debug|Any CPU - {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|arm64.ActiveCfg = Debug|Any CPU - {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x64.ActiveCfg = Debug|Any CPU - {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A}.Checked|x86.ActiveCfg = Debug|Any CPU + {008873D5-9028-4FF3-8354-71F713748625}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm.ActiveCfg = Debug|Any CPU + {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm64.ActiveCfg = Debug|Any CPU + {008873D5-9028-4FF3-8354-71F713748625}.Checked|x64.ActiveCfg = Debug|Any CPU + {008873D5-9028-4FF3-8354-71F713748625}.Checked|x86.ActiveCfg = Debug|Any CPU {008873D5-9028-4FF3-8354-71F713748625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {008873D5-9028-4FF3-8354-71F713748625}.Debug|Any CPU.Build.0 = Debug|Any CPU {008873D5-9028-4FF3-8354-71F713748625}.Debug|arm.ActiveCfg = Debug|Any CPU @@ -774,53 +783,53 @@ Global {008873D5-9028-4FF3-8354-71F713748625}.Release|x64.Build.0 = Release|Any CPU {008873D5-9028-4FF3-8354-71F713748625}.Release|x86.ActiveCfg = Release|Any CPU {008873D5-9028-4FF3-8354-71F713748625}.Release|x86.Build.0 = Release|Any CPU - {008873D5-9028-4FF3-8354-71F713748625}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm.ActiveCfg = Debug|Any CPU - {008873D5-9028-4FF3-8354-71F713748625}.Checked|arm64.ActiveCfg = Debug|Any CPU - {008873D5-9028-4FF3-8354-71F713748625}.Checked|x64.ActiveCfg = Debug|Any CPU - {008873D5-9028-4FF3-8354-71F713748625}.Checked|x86.ActiveCfg = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {0F7BA062-C34C-41A8-840F-F0B074B18686} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} + {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C} + {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2} = {32CDDDCD-5319-494C-AB41-42B87C467F04} {FC1007CC-9E52-49B7-A47B-A8AE76E75986} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} + {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3} = {32CDDDCD-5319-494C-AB41-42B87C467F04} {B79E5BB4-2595-48BC-A44C-0A7949AFBDEB} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} + {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8} = {32CDDDCD-5319-494C-AB41-42B87C467F04} {C1C606F3-A246-4EA0-A467-3AC4F31C2AFE} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} + {8CFB1155-26A2-43E3-B192-1F87D9E543AC} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} + {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08} = {32CDDDCD-5319-494C-AB41-42B87C467F04} {74143A5F-6987-4AB5-B786-DE358F01241B} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} + {CE5E53C1-F9B5-41EE-8D00-837913EC57D1} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} + {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1} = {32CDDDCD-5319-494C-AB41-42B87C467F04} {71A845ED-4344-41FC-8FCA-3AC9B6BA6C45} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} - {1EB2EBE2-12EA-4545-B390-098F083329A1} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} - {04A40E6C-DD10-473D-AFF8-9033E936DC46} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} - {424A7718-F5B7-41FB-A74B-1E23A9BF13EA} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} - {8683B814-5459-4412-A881-ECAFF9ED1781} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} - {ED86AB26-1CFB-457D-BF87-B7A0D8FAF272} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C} {BFED925C-18F2-4C98-833E-66F205234598} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C} {765B4AA5-723A-44FF-BC4E-EB0F03103F6D} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C} + {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} + {B4E3E774-2C16-4CBF-87EF-88C547529B94} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} {EC3ADEFA-1FF3-482C-8CCB-FE4C77292532} = {26A72FFB-871A-4F2F-A513-B2F6E09F358C} - {BC2F0477-9A34-48D3-B66F-AE97AEA29CD2} = {32CDDDCD-5319-494C-AB41-42B87C467F04} - {8B1D80E9-AE0D-4E3C-9F91-E6862B49AEF3} = {32CDDDCD-5319-494C-AB41-42B87C467F04} - {E00AE8BB-7C7F-4D07-949D-EDCC815AC8C8} = {32CDDDCD-5319-494C-AB41-42B87C467F04} - {D549C13B-FC0D-4B5A-B50D-8F74CB5A3D08} = {32CDDDCD-5319-494C-AB41-42B87C467F04} - {28278E01-BF5C-4AB6-AA7A-8DD4E6C04DB1} = {32CDDDCD-5319-494C-AB41-42B87C467F04} {44BAE6F1-94C2-415B-9A16-3B8EC429B09B} = {32CDDDCD-5319-494C-AB41-42B87C467F04} + {1EB2EBE2-12EA-4545-B390-098F083329A1} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} {B18C5A3A-CAB0-4B62-9C01-7A046E05089F} = {32CDDDCD-5319-494C-AB41-42B87C467F04} + {04A40E6C-DD10-473D-AFF8-9033E936DC46} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} {B86E4599-88CF-4662-96BA-3FCB926D0BA1} = {32CDDDCD-5319-494C-AB41-42B87C467F04} + {424A7718-F5B7-41FB-A74B-1E23A9BF13EA} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} {D620CBA3-326B-4E4A-81C2-3D9E9258E45C} = {32CDDDCD-5319-494C-AB41-42B87C467F04} - {8CFB1155-26A2-43E3-B192-1F87D9E543AC} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} - {CE5E53C1-F9B5-41EE-8D00-837913EC57D1} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} - {09AA6758-0BD3-4312-9C07-AE9F1D50A3AD} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} - {B4E3E774-2C16-4CBF-87EF-88C547529B94} = {39B30F44-B141-44E9-B7A7-B1A9EDB1A61C} + {8683B814-5459-4412-A881-ECAFF9ED1781} = {D819DEB6-6F6B-484B-9F0F-BDBCEDC83A1A} {4D8B7538-D933-4F3A-818D-4E19ABA7E182} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F} {6C60944F-4FE1-450F-884B-D523EDFCFAB3} = {1A04C5D7-1DE9-47C3-BCC1-147678B9085F} - {1A04C5D7-1DE9-47C3-BCC1-147678B9085F} = {7392B838-42AF-4F54-AD02-366397DAF640} {B8F2E56D-6571-466D-9EF2-9FCAD3FC6E5B} = {32733782-56D6-4EAF-B94E-5D10C759DD57} {42F9A600-BEC3-4F87-97EE-38E0DCAABC5A} = {32733782-56D6-4EAF-B94E-5D10C759DD57} - {32733782-56D6-4EAF-B94E-5D10C759DD57} = {7392B838-42AF-4F54-AD02-366397DAF640} {008873D5-9028-4FF3-8354-71F713748625} = {19EA33B4-0E87-451F-95E3-8F3959117654} + {1A04C5D7-1DE9-47C3-BCC1-147678B9085F} = {7392B838-42AF-4F54-AD02-366397DAF640} + {32733782-56D6-4EAF-B94E-5D10C759DD57} = {7392B838-42AF-4F54-AD02-366397DAF640} {19EA33B4-0E87-451F-95E3-8F3959117654} = {7392B838-42AF-4F54-AD02-366397DAF640} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3FE64246-4AFA-424A-AE5D-7007E20451B5} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{0f7ba062-c34c-41a8-840f-f0b074b18686}*SharedItemsImports = 5 + ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{42f9a600-bec3-4f87-97ee-38e0dcaabc5a}*SharedItemsImports = 5 + ..\..\tools\illink\src\ILLink.Shared\ILLink.Shared.projitems*{6c60944f-4fe1-450f-884b-d523edfcfab3}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs index 6faf786f3bd539..c7bb4a81d3bd56 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/Interop/JavaScriptExports.cs @@ -123,18 +123,25 @@ public static void CallDelegate(JSMarshalerArgument* arguments_buffer) // arg_2 set by JS caller when there are arguments // arg_3 set by JS caller when there are arguments // arg_4 set by JS caller when there are arguments +#if !FEATURE_WASM_MANAGED_THREADS try { -#if FEATURE_WASM_MANAGED_THREADS - // when we arrive here, we are on the thread which owns the proxies - // if we need to dispatch the call to another thread in the future - // we may need to consider how to solve blocking of the synchronous call - // see also https://github.com/dotnet/runtime/issues/76958#issuecomment-1921418290 - arg_exc.AssertCurrentThreadContext(); +#else + // when we arrive here, we are on the thread which owns the proxies + var ctx = arg_exc.AssertCurrentThreadContext(); - if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.AllowBlockingWaitInAsyncCode) + try + { + if (ctx.IsMainThread) { - Thread.ThrowOnBlockingWaitOnJSInteropThread = true; + if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.ThrowWhenBlockingWait) + { + Thread.ThrowOnBlockingWaitOnJSInteropThread = true; + } + else if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.WarnWhenBlockingWait) + { + Thread.WarnOnBlockingWaitOnJSInteropThread = true; + } } #endif @@ -156,9 +163,16 @@ public static void CallDelegate(JSMarshalerArgument* arguments_buffer) #if FEATURE_WASM_MANAGED_THREADS finally { - if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.AllowBlockingWaitInAsyncCode) + if (ctx.IsMainThread) { - Thread.ThrowOnBlockingWaitOnJSInteropThread = false; + if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.ThrowWhenBlockingWait) + { + Thread.ThrowOnBlockingWaitOnJSInteropThread = false; + } + else if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.WarnWhenBlockingWait) + { + Thread.WarnOnBlockingWaitOnJSInteropThread = false; + } } } #endif @@ -189,12 +203,9 @@ public static void CompleteTask(JSMarshalerArgument* arguments_buffer) } } - if (holder.CallbackReady != null) - { -#pragma warning disable CA1416 // Validate platform compatibility - Thread.ForceBlockingWait(static (callbackReady) => ((ManualResetEventSlim)callbackReady!).Wait(), holder.CallbackReady); -#pragma warning restore CA1416 // Validate platform compatibility - } + // this is always running on I/O thread, so it will not throw PNSE + // it's also OK to block here, because we know we will only block shortly, as this is just race with the other thread. + holder.CallbackReady?.Wait(); lock (ctx) { @@ -247,21 +258,17 @@ public static void GetManagedStackTrace(JSMarshalerArgument* arguments_buffer) // this is here temporarily, until JSWebWorker becomes public API [DynamicDependency(DynamicallyAccessedMemberTypes.NonPublicMethods, "System.Runtime.InteropServices.JavaScript.JSWebWorker", "System.Runtime.InteropServices.JavaScript")] - // the marshaled signature is: GCHandle InstallMainSynchronizationContext(nint jsNativeTID, JSThreadBlockingMode jsThreadBlockingMode, JSThreadInteropMode jsThreadInteropMode, MainThreadingMode mainThreadingMode) + // the marshaled signature is: GCHandle InstallMainSynchronizationContext(nint jsNativeTID, JSThreadBlockingMode jsThreadBlockingMode) public static void InstallMainSynchronizationContext(JSMarshalerArgument* arguments_buffer) { ref JSMarshalerArgument arg_exc = ref arguments_buffer[0]; // initialized by caller in alloc_stack_frame() ref JSMarshalerArgument arg_res = ref arguments_buffer[1];// initialized and set by caller ref JSMarshalerArgument arg_1 = ref arguments_buffer[2];// initialized and set by caller ref JSMarshalerArgument arg_2 = ref arguments_buffer[3];// initialized and set by caller - ref JSMarshalerArgument arg_3 = ref arguments_buffer[4];// initialized and set by caller - ref JSMarshalerArgument arg_4 = ref arguments_buffer[5];// initialized and set by caller try { JSProxyContext.ThreadBlockingMode = (JSHostImplementation.JSThreadBlockingMode)arg_2.slot.Int32Value; - JSProxyContext.ThreadInteropMode = (JSHostImplementation.JSThreadInteropMode)arg_3.slot.Int32Value; - JSProxyContext.MainThreadingMode = (JSHostImplementation.MainThreadingMode)arg_4.slot.Int32Value; var jsSynchronizationContext = JSSynchronizationContext.InstallWebWorkerInterop(true, CancellationToken.None); jsSynchronizationContext.ProxyContext.JSNativeTID = arg_1.slot.IntPtrValue; arg_res.slot.GCHandle = jsSynchronizationContext.ProxyContext.ContextHandle; @@ -283,9 +290,16 @@ public static void BeforeSyncJSExport(JSMarshalerArgument* arguments_buffer) { var ctx = arg_exc.AssertCurrentThreadContext(); ctx.IsPendingSynchronousCall = true; - if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.AllowBlockingWaitInAsyncCode) + if (ctx.IsMainThread) { - Thread.ThrowOnBlockingWaitOnJSInteropThread = true; + if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.ThrowWhenBlockingWait) + { + Thread.ThrowOnBlockingWaitOnJSInteropThread = true; + } + else if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.WarnWhenBlockingWait) + { + Thread.WarnOnBlockingWaitOnJSInteropThread = true; + } } } catch (Exception ex) @@ -305,9 +319,16 @@ public static void AfterSyncJSExport(JSMarshalerArgument* arguments_buffer) { var ctx = arg_exc.AssertCurrentThreadContext(); ctx.IsPendingSynchronousCall = false; - if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.AllowBlockingWaitInAsyncCode) + if (ctx.IsMainThread) { - Thread.ThrowOnBlockingWaitOnJSInteropThread = false; + if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.ThrowWhenBlockingWait) + { + Thread.ThrowOnBlockingWaitOnJSInteropThread = false; + } + else if (JSProxyContext.ThreadBlockingMode == JSHostImplementation.JSThreadBlockingMode.WarnWhenBlockingWait) + { + Thread.WarnOnBlockingWaitOnJSInteropThread = false; + } } } catch (Exception ex) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs index 550956cce3309a..c4963b52d04a37 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSFunctionBinding.cs @@ -230,11 +230,7 @@ internal static unsafe void InvokeJSFunction(JSObject jsFunction, Span arguments) { #if FEATURE_WASM_MANAGED_THREADS - if (JSProxyContext.ThreadInteropMode == JSHostImplementation.JSThreadInteropMode.NoSyncJSInterop) - { - throw new PlatformNotSupportedException("Cannot call synchronous JS functions."); - } - else if (jsFunction.ProxyContext.IsPendingSynchronousCall) + if (jsFunction.ProxyContext.IsPendingSynchronousCall && jsFunction.ProxyContext.IsMainThread) { throw new PlatformNotSupportedException("Cannot call synchronous JS function from inside a synchronous call to a C# method."); } @@ -260,11 +256,7 @@ internal static unsafe void InvokeJSFunctionCurrent(JSObject jsFunction, Span arguments) { #if FEATURE_WASM_MANAGED_THREADS - if (JSProxyContext.ThreadInteropMode == JSHostImplementation.JSThreadInteropMode.NoSyncJSInterop) - { - throw new PlatformNotSupportedException("Cannot call synchronous JS functions."); - } - else if (jsFunction.ProxyContext.IsPendingSynchronousCall) + if (jsFunction.ProxyContext.IsPendingSynchronousCall && jsFunction.ProxyContext.IsMainThread) { throw new PlatformNotSupportedException("Cannot call synchronous JS function from inside a synchronous call to a C# method."); } @@ -274,10 +266,8 @@ internal static unsafe void DispatchJSFunctionSync(JSObject jsFunction, Span(async () => try { var promise = response.Content.ReadAsStringAsync(cts.Token); - Console.WriteLine("HttpClient_CancelInDifferentThread: ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); + WebWorkerTestHelper.Log("HttpClient_CancelInDifferentThread: ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); cts.Cancel(); await promise; } catch (TaskCanceledException ex) { - Console.WriteLine("HttpClient_CancelInDifferentThread: TaskCanceledException is thrown with message: " + ex.ToString()); + WebWorkerTestHelper.Log("HttpClient_CancelInDifferentThread: TaskCanceledException is thrown with message: " + ex.ToString()); throw; } catch (OperationCanceledException ex) { - Console.WriteLine("HttpClient_CancelInDifferentThread: OperationCanceledException is thrown with message: " + ex.ToString()); + WebWorkerTestHelper.Log("HttpClient_CancelInDifferentThread: OperationCanceledException is thrown with message: " + ex.ToString()); throw; } }); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.cs index c67bac997294b9..0a2ae44142dc35 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTest.cs @@ -11,15 +11,9 @@ namespace System.Runtime.InteropServices.JavaScript.Tests // TODO test: // JSExport 2x - // JSExport async - // lock - // thread allocation, many threads // ProxyContext flow, child thread, child task // use JSObject after JSWebWorker finished, especially HTTP - // WS on JSWebWorker - // HTTP continue on TP // event pipe - // FS // JS setTimeout till after JSWebWorker close // synchronous .Wait for JS setTimeout on the same thread -> deadlock problem **7)** @@ -159,7 +153,7 @@ public async Task JSSynchronizationContext_Send_Post_Items_Cancellation() } catch (Exception ex) { - Console.WriteLine("Unexpected exception " + ex); + WebWorkerTestHelper.Log("Unexpected exception " + ex); postReady.SetException(ex); return Task.FromException(ex); } @@ -344,7 +338,7 @@ public async Task ManagedConsole(Executor executor) using var cts = CreateTestCaseTimeoutSource(); await executor.Execute(() => { - Console.WriteLine("C# Hello from ManagedThreadId: " + Environment.CurrentManagedThreadId); + WebWorkerTestHelper.Log("C# Hello from ManagedThreadId: " + Environment.CurrentManagedThreadId); Console.Clear(); return Task.CompletedTask; }, cts.Token); @@ -392,7 +386,7 @@ public async Task ThreadingTimer(Executor executor) await executor.Execute(async () => { TaskCompletionSource tcs = new TaskCompletionSource(); - Console.WriteLine("ThreadingTimer: Start Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); + WebWorkerTestHelper.Log("ThreadingTimer: Start Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); using var timer = new Timer(_ => { @@ -405,7 +399,7 @@ await executor.Execute(async () => await tcs.Task; }, cts.Token); - Console.WriteLine("ThreadingTimer: End Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); + WebWorkerTestHelper.Log("ThreadingTimer: End Time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); Assert.True(hit); } @@ -496,7 +490,7 @@ await executor.Execute(async () => } [Theory, MemberData(nameof(GetTargetThreadsAndBlockingCalls))] - public async Task WaitDoesNotAssertInAsyncCode(Executor executor, NamedCall method) + public async Task WaitInAsyncAssertsOnlyOnJSWebWorker(Executor executor, NamedCall method) { using var cts = CreateTestCaseTimeoutSource(); await executor.Execute(async () => @@ -513,7 +507,15 @@ await executor.Execute(async () => exception = ex; } - Assert.Null(exception); + if (method.IsBlocking && executor.Type == ExecutorType.JSWebWorker) + { + Assert.NotNull(exception); + Assert.IsType(exception); + } + else + { + Assert.Null(exception); + } }, cts.Token); } @@ -527,7 +529,8 @@ await executor.Execute(async () => Exception? exception = null; // the callback will hit Main or JSWebWorker, not the original executor thread - await WebWorkerTestHelper.CallMeBackSync(() => { + await WebWorkerTestHelper.CallMeBackSync(() => + { // when we are inside of synchronous callback, all blocking .Wait is forbidden try { @@ -539,9 +542,15 @@ await WebWorkerTestHelper.CallMeBackSync(() => { } }); - Console.WriteLine("WaitAssertsOnJSInteropThreads: ExecuterType: " + executor.Type + " ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); - Assert.NotNull(exception); - Assert.IsType(exception); + if (method.IsBlocking) + { + Assert.NotNull(exception); + Assert.IsType(exception); + } + else + { + Assert.Null(exception); + } }, cts.Token); } @@ -558,9 +567,15 @@ await executor.Execute(async () => // the callback will hit Main or JSWebWorker, not the original executor thread await WebWorkerTestHelper.CallExportBackSync(nameof(WebWorkerTestHelper.CallCurrentCallback)); - Console.WriteLine("WaitAssertsOnJSInteropThreads: ExecuterType: " + executor.Type + " ManagedThreadId: " + Environment.CurrentManagedThreadId + " NativeThreadId: " + WebWorkerTestHelper.NativeThreadId); - Assert.NotNull(WebWorkerTestHelper.LastException); - Assert.IsType(WebWorkerTestHelper.LastException); + if (method.IsBlocking) + { + Assert.NotNull(WebWorkerTestHelper.LastException); + Assert.IsType(WebWorkerTestHelper.LastException); + } + else + { + Assert.Null(WebWorkerTestHelper.LastException); + } }, cts.Token); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestBase.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestBase.cs index 3fb53d484def06..b2c11b59882199 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestBase.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestBase.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; using System.Threading.Tasks; using System.Threading; using Xunit; @@ -35,7 +36,7 @@ protected CancellationTokenSource CreateTestCaseTimeoutSource([CallerMemberName] cts.Token.Register(() => { var end = DateTime.Now; - Console.WriteLine($"Unexpected test case {memberName} timeout after {end - start} ManagedThreadId:{Environment.CurrentManagedThreadId}"); + WebWorkerTestHelper.Log($"Unexpected test case {memberName} timeout after {end - start} ManagedThreadId:{Environment.CurrentManagedThreadId}"); }); return cts; } @@ -90,7 +91,7 @@ async Task ActionsInDifferentThreads1() } catch (Exception ex) { - Console.WriteLine("ActionsInDifferentThreads1 failed\n" + ex); + WebWorkerTestHelper.Log("ActionsInDifferentThreads1 failed\n" + ex); job1ReadyTCS.SetResult(default); e1Failed = true; throw; @@ -135,35 +136,64 @@ async Task ActionsInDifferentThreads2() { throw; } - Console.WriteLine("ActionsInDifferentThreads failed with: \n" + ex); + WebWorkerTestHelper.Log("ActionsInDifferentThreads failed with: \n" + ex); if (!e1Done || !e2Done) { - Console.WriteLine("ActionsInDifferentThreads canceling!"); + WebWorkerTestHelper.Log("ActionsInDifferentThreads canceling!"); cts.Cancel(); } throw; } } + static void LocalCtsIgnoringCall(Action action) + { + var cts = new CancellationTokenSource(8); + try + { + action(cts.Token); + } + catch (OperationCanceledException exception) + { + if (exception.CancellationToken != cts.Token) + { + throw; + } + /* ignore the local one */ + } + } + public static IEnumerable BlockingCalls = new List { - new NamedCall { Name = "Task.Wait", Call = delegate (CancellationToken ct) { Task.Delay(10, ct).Wait(ct); }}, - new NamedCall { Name = "Task.WaitAll", Call = delegate (CancellationToken ct) { Task.WaitAll(Task.Delay(10, ct)); }}, - new NamedCall { Name = "Task.WaitAny", Call = delegate (CancellationToken ct) { Task.WaitAny(Task.Delay(10, ct)); }}, - new NamedCall { Name = "ManualResetEventSlim.Wait", Call = delegate (CancellationToken ct) { + // new NamedCall { IsBlocking = false, Name = "Console.WriteLine", Call = delegate (CancellationToken ct) { Console.WriteLine("Blocking"); }}, + // new NamedCall { IsBlocking = false, Name = "Directory.GetCurrentDirectory", Call = delegate (CancellationToken ct) { Directory.GetCurrentDirectory(); }}, + new NamedCall { IsBlocking = true, Name = "Task.Wait", Call = delegate (CancellationToken ct) { Task.Delay(10, ct).Wait(ct); }}, + new NamedCall { IsBlocking = true, Name = "Task.WaitAll", Call = delegate (CancellationToken ct) { Task.WaitAll(Task.Delay(10, ct)); }}, + new NamedCall { IsBlocking = true, Name = "Task.WaitAny", Call = delegate (CancellationToken ct) { Task.WaitAny(Task.Delay(10, ct)); }}, + new NamedCall { IsBlocking = true, Name = "ManualResetEventSlim.Wait", Call = delegate (CancellationToken ct) { + using var mr = new ManualResetEventSlim(false); + LocalCtsIgnoringCall(mr.Wait); + }}, + new NamedCall { IsBlocking = true, Name = "SemaphoreSlim.Wait", Call = delegate (CancellationToken ct) { + using var sem = new SemaphoreSlim(2); + LocalCtsIgnoringCall(sem.Wait); + }}, + /*new NamedCall { IsBlocking = true, Name = "CancellationTokenSource.ctor", Call = delegate (CancellationToken ct) { + using var cts = new CancellationTokenSource(8); + }}, + new NamedCall { IsBlocking = true, Name = "Mutex.WaitOne", Call = delegate (CancellationToken ct) { using var mr = new ManualResetEventSlim(false); - using var cts = new CancellationTokenSource(8); - try { - mr.Wait(cts.Token); - } catch (OperationCanceledException) { /* ignore */ } - }}, - new NamedCall { Name = "SemaphoreSlim.Wait", Call = delegate (CancellationToken ct) { - using var sem = new SemaphoreSlim(2); - var cts = new CancellationTokenSource(8); - try { - sem.Wait(cts.Token); - } catch (OperationCanceledException) { /* ignore */ } - }}, + var mutex = new Mutex(); + var thread = new Thread(() => { + mutex.WaitOne(); + mr.Set(); + Thread.Sleep(50); + mutex.ReleaseMutex(); + }); + thread.Start(); + Thread.ForceBlockingWait(static (b) => ((ManualResetEventSlim)b).Wait(), mr); + mutex.WaitOne(); + }},*/ }; public static IEnumerable GetTargetThreadsAndBlockingCalls() diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestHelper.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestHelper.cs index 1fc94b83adba99..fa83846f149291 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestHelper.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/WebWorkerTestHelper.cs @@ -48,7 +48,7 @@ public partial class WebWorkerTestHelper public static NamedCall CurrentCallback; public static CancellationToken CurrentCancellationToken = CancellationToken.None; public static Exception? LastException = null; - + [JSExport] public static void CallCurrentCallback() { @@ -333,7 +333,7 @@ public static Task RunOnNewThread(Func job, CancellationToken cancellation } catch (Exception ex) { - if(ex is AggregateException agg) + if (ex is AggregateException agg) { tcs.TrySetException(agg.InnerException); } @@ -385,10 +385,10 @@ public static Task RunOnTargetAsync(SynchronizationContext ctx, Func job, public class NamedCall { public string Name { get; set; } + public bool IsBlocking { get; set; } public delegate void Method(CancellationToken ct); public Method Call { get; set; } override public string ToString() => Name; } - } diff --git a/src/libraries/System.Threading.Thread/src/CompatibilitySuppressions.Threading.xml b/src/libraries/System.Threading.Thread/src/CompatibilitySuppressions.Threading.xml index 5fc41e30ed4415..8eb2f78e6a7066 100644 --- a/src/libraries/System.Threading.Thread/src/CompatibilitySuppressions.Threading.xml +++ b/src/libraries/System.Threading.Thread/src/CompatibilitySuppressions.Threading.xml @@ -20,6 +20,10 @@ CP0002 F:System.Threading.Thread.ThrowOnBlockingWaitOnJSInteropThread + + CP0002 + F:System.Threading.Thread.WarnOnBlockingWaitOnJSInteropThread + CP0002 M:System.Threading.Thread.AssureBlockingPossible diff --git a/src/mono/browser/runtime/corebindings.c b/src/mono/browser/runtime/corebindings.c index 1b0c0a809f63ef..eecc9b69e86e1d 100644 --- a/src/mono/browser/runtime/corebindings.c +++ b/src/mono/browser/runtime/corebindings.c @@ -51,6 +51,7 @@ void mono_wasm_invoke_js_function_send (pthread_t target_tid, int function_js_ha extern void mono_threads_wasm_async_run_in_target_thread_vi (pthread_t target_thread, void (*func) (gpointer), gpointer user_data1); extern void mono_threads_wasm_async_run_in_target_thread_vii (pthread_t target_thread, void (*func) (gpointer, gpointer), gpointer user_data1, gpointer user_data2); extern void mono_threads_wasm_sync_run_in_target_thread_vii (pthread_t target_thread, void (*func) (gpointer, gpointer), gpointer user_data1, gpointer user_data2); +extern void mono_wasm_warn_about_blocking_wait (void* ptr, int32_t length); #else extern void mono_wasm_bind_js_import (void *signature, int *is_exception, MonoObject **result); extern void mono_wasm_invoke_jsimport_ST (int function_handle, void *args); @@ -85,6 +86,7 @@ void bindings_initialize_internals (void) mono_add_internal_call ("Interop/Runtime::InvokeJSImportAsyncPost", mono_wasm_invoke_jsimport_async_post); mono_add_internal_call ("Interop/Runtime::InvokeJSFunctionSend", mono_wasm_invoke_js_function_send); mono_add_internal_call ("Interop/Runtime::CancelPromisePost", mono_wasm_cancel_promise_post); + mono_add_internal_call ("System.Threading.Thread::WarnAboutBlockingWait", mono_wasm_warn_about_blocking_wait); #else mono_add_internal_call ("Interop/Runtime::BindJSImport", mono_wasm_bind_js_import); mono_add_internal_call ("Interop/Runtime::InvokeJSImportST", mono_wasm_invoke_jsimport_ST); diff --git a/src/mono/browser/runtime/exports-binding.ts b/src/mono/browser/runtime/exports-binding.ts index d2ff55bc088a70..81f9cc764b1ded 100644 --- a/src/mono/browser/runtime/exports-binding.ts +++ b/src/mono/browser/runtime/exports-binding.ts @@ -29,7 +29,7 @@ import { mono_wasm_cancel_promise } from "./cancelable-promise"; import { mono_wasm_start_deputy_thread_async, mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_unregistered, - mono_wasm_pthread_on_pthread_registered, mono_wasm_pthread_set_name, mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop, mono_wasm_start_io_thread_async + mono_wasm_pthread_on_pthread_registered, mono_wasm_pthread_set_name, mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop, mono_wasm_start_io_thread_async, mono_wasm_warn_about_blocking_wait } from "./pthreads"; import { mono_wasm_dump_threads } from "./pthreads/ui-thread"; @@ -56,6 +56,8 @@ export const mono_wasm_threads_imports = !WasmEnableThreads ? [] : [ mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop, mono_wasm_invoke_jsimport, + mono_wasm_warn_about_blocking_wait, + ]; export const mono_wasm_imports = [ diff --git a/src/mono/browser/runtime/interp-pgo.ts b/src/mono/browser/runtime/interp-pgo.ts index c4214b4fe5d6a3..79678489df6e26 100644 --- a/src/mono/browser/runtime/interp-pgo.ts +++ b/src/mono/browser/runtime/interp-pgo.ts @@ -206,9 +206,7 @@ export async function getCacheKey(prefix: string): Promise { delete inputs.enableDownloadRetry; delete inputs.extensions; delete inputs.runtimeId; - delete inputs.mainThreadingMode; delete inputs.jsThreadBlockingMode; - delete inputs.jsThreadInteropMode; inputs.GitHash = loaderHelpers.gitHash; inputs.ProductVersion = ProductVersion; diff --git a/src/mono/browser/runtime/invoke-js.ts b/src/mono/browser/runtime/invoke-js.ts index cb26b89a73b79f..b7913c624f531d 100644 --- a/src/mono/browser/runtime/invoke-js.ts +++ b/src/mono/browser/runtime/invoke-js.ts @@ -17,6 +17,7 @@ import { mono_log_debug, mono_wasm_symbolicate_string } from "./logging"; import { mono_wasm_get_jsobj_from_js_handle } from "./gc-handles"; import { endMeasure, MeasuredBlock, startMeasure } from "./profiler"; import { wrap_as_cancelable_promise } from "./cancelable-promise"; +import { monoThreadInfo } from "./pthreads"; export const js_import_wrapper_by_fn_handle: Function[] = [null];// 0th slot is dummy, main thread we free them on shutdown. On web worker thread we free them when worker is detached. @@ -134,8 +135,16 @@ function bind_js_import(signature: JSFunctionSignature): Function { } function async_bound_fn(args: JSMarshalerArguments): void { - forceThreadMemoryViewRefresh(); - bound_fn(args); + if (WasmEnableThreads && monoThreadInfo.isUI) { + // make sure we are not blocking em_task_queue_execute up the call stack + // so that when bound_fn calls back to managed, C# calls to the FS/console could still be processed + forceThreadMemoryViewRefresh(); + bound_fn(args); + /*Module.safeSetTimeout(() => { + }, 0);*/ + } else { + bound_fn(args); + } } function sync_bound_fn(args: JSMarshalerArguments): void { diff --git a/src/mono/browser/runtime/loader/config.ts b/src/mono/browser/runtime/loader/config.ts index 07b7750a2a2c65..5ba2a4476df014 100644 --- a/src/mono/browser/runtime/loader/config.ts +++ b/src/mono/browser/runtime/loader/config.ts @@ -4,7 +4,7 @@ import BuildConfiguration from "consts:configuration"; import WasmEnableThreads from "consts:wasmEnableThreads"; -import { MainThreadingMode, type DotnetModuleInternal, type MonoConfigInternal, JSThreadBlockingMode, JSThreadInteropMode } from "../types/internal"; +import { type DotnetModuleInternal, type MonoConfigInternal, JSThreadBlockingMode } from "../types/internal"; import type { DotnetModuleConfig, MonoConfig, ResourceGroups, ResourceList } from "../types"; import { exportedRuntimeAPI, loaderHelpers, runtimeHelpers } from "./globals"; import { mono_log_error, mono_log_debug } from "./logging"; @@ -12,7 +12,6 @@ import { importLibraryInitializers, invokeLibraryInitializers } from "./libraryI import { mono_exit } from "./exit"; import { makeURLAbsoluteWithApplicationBase } from "./polyfills"; import { appendUniqueQuery } from "./assets"; -import { mono_log_warn } from "./logging"; export function deep_merge_config(target: MonoConfigInternal, source: MonoConfigInternal): MonoConfigInternal { // no need to merge the same object @@ -198,40 +197,8 @@ export function normalizeConfig() { if (!Number.isInteger(config.finalizerThreadStartDelayMs)) { config.finalizerThreadStartDelayMs = 200; } - if (config.mainThreadingMode == undefined) { - config.mainThreadingMode = MainThreadingMode.DeputyAndIOThreads; - } if (config.jsThreadBlockingMode == undefined) { - config.jsThreadBlockingMode = JSThreadBlockingMode.AllowBlockingWaitInAsyncCode; - } - if (config.jsThreadInteropMode == undefined) { - config.jsThreadInteropMode = JSThreadInteropMode.SimpleSynchronousJSInterop; - } - let validModes = false; - if (config.mainThreadingMode == MainThreadingMode.DeputyThread - && config.jsThreadBlockingMode == JSThreadBlockingMode.NoBlockingWait - && config.jsThreadInteropMode == JSThreadInteropMode.SimpleSynchronousJSInterop - ) { - validModes = true; - } - else if (config.mainThreadingMode == MainThreadingMode.DeputyAndIOThreads - && config.jsThreadBlockingMode == JSThreadBlockingMode.AllowBlockingWaitInAsyncCode - && config.jsThreadInteropMode == JSThreadInteropMode.SimpleSynchronousJSInterop - ) { - validModes = true; - } - else if (config.mainThreadingMode == MainThreadingMode.DeputyThread - && config.jsThreadBlockingMode == JSThreadBlockingMode.AllowBlockingWait - && config.jsThreadInteropMode == JSThreadInteropMode.SimpleSynchronousJSInterop - ) { - validModes = true; - } - if (!validModes) { - mono_log_warn("Unsupported threading configuration", { - mainThreadingMode: config.mainThreadingMode, - jsThreadBlockingMode: config.jsThreadBlockingMode, - jsThreadInteropMode: config.jsThreadInteropMode - }); + config.jsThreadBlockingMode = JSThreadBlockingMode.PreventSynchronousJSExport; } } diff --git a/src/mono/browser/runtime/managed-exports.ts b/src/mono/browser/runtime/managed-exports.ts index df99745d6af376..1b9be70d1b2035 100644 --- a/src/mono/browser/runtime/managed-exports.ts +++ b/src/mono/browser/runtime/managed-exports.ts @@ -3,7 +3,7 @@ import WasmEnableThreads from "consts:wasmEnableThreads"; -import { GCHandle, GCHandleNull, JSMarshalerArguments, JSThreadInteropMode, MarshalerToCs, MarshalerToJs, MarshalerType, MonoMethod, PThreadPtr } from "./types/internal"; +import { GCHandle, GCHandleNull, JSMarshalerArguments, JSThreadBlockingMode, MarshalerToCs, MarshalerToJs, MarshalerType, MonoMethod, PThreadPtr } from "./types/internal"; import cwraps, { threads_c_functions as twraps } from "./cwraps"; import { runtimeHelpers, Module, loaderHelpers, mono_assert } from "./globals"; import { JavaScriptMarshalerArgSize, alloc_stack_frame, get_arg, get_arg_gc_handle, is_args_exception, set_arg_i32, set_arg_intptr, set_arg_type, set_gc_handle, set_receiver_should_free } from "./marshal"; @@ -165,11 +165,13 @@ export function complete_task(holder_gc_handle: GCHandle, error?: any, data?: an export function call_delegate(callback_gc_handle: GCHandle, arg1_js: any, arg2_js: any, arg3_js: any, res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs, arg3_converter?: MarshalerToCs) { loaderHelpers.assert_runtime_running(); if (WasmEnableThreads) { - if (runtimeHelpers.config.jsThreadInteropMode == JSThreadInteropMode.NoSyncJSInterop) { - throw new Error("Cannot call synchronous C# methods."); - } - else if (runtimeHelpers.isPendingSynchronousCall) { - throw new Error("Cannot call synchronous C# method from inside a synchronous call to a JS method."); + if (monoThreadInfo.isUI) { + if (runtimeHelpers.config.jsThreadBlockingMode == JSThreadBlockingMode.PreventSynchronousJSExport) { + throw new Error("Cannot call synchronous C# methods."); + } + else if (runtimeHelpers.isPendingSynchronousCall) { + throw new Error("Cannot call synchronous C# method from inside a synchronous call to a JS method."); + } } } const sp = Module.stackSave(); @@ -226,26 +228,22 @@ export function get_managed_stack_trace(exception_gc_handle: GCHandle) { } } -// GCHandle InstallMainSynchronizationContext(nint jsNativeTID, JSThreadBlockingMode jsThreadBlockingMode, JSThreadInteropMode jsThreadInteropMode, MainThreadingMode mainThreadingMode) -export function install_main_synchronization_context(jsThreadBlockingMode: number, jsThreadInteropMode: number, mainThreadingMode: number): GCHandle { +// GCHandle InstallMainSynchronizationContext(nint jsNativeTID, JSThreadBlockingMode jsThreadBlockingMode) +export function install_main_synchronization_context(jsThreadBlockingMode: number): GCHandle { if (!WasmEnableThreads) return GCHandleNull; assert_c_interop(); try { // this block is like alloc_stack_frame() but without set_args_context() - const bytes = JavaScriptMarshalerArgSize * 6; + const bytes = JavaScriptMarshalerArgSize * 4; const args = Module.stackAlloc(bytes) as any; _zero_region(args, bytes); const res = get_arg(args, 1); const arg1 = get_arg(args, 2); const arg2 = get_arg(args, 3); - const arg3 = get_arg(args, 4); - const arg4 = get_arg(args, 5); set_arg_intptr(arg1, mono_wasm_main_thread_ptr() as any); set_arg_i32(arg2, jsThreadBlockingMode); - set_arg_i32(arg3, jsThreadInteropMode); - set_arg_i32(arg4, mainThreadingMode); // this block is like invoke_sync_jsexport() but without assert_js_interop() cwraps.mono_wasm_invoke_jsexport(managedExports.InstallMainSynchronizationContext!, args); @@ -282,11 +280,13 @@ export function invoke_sync_jsexport(method: MonoMethod, args: JSMarshalerArgume if (!WasmEnableThreads) { cwraps.mono_wasm_invoke_jsexport(method, args as any); } else { - if (runtimeHelpers.config.jsThreadInteropMode == JSThreadInteropMode.NoSyncJSInterop) { - throw new Error("Cannot call synchronous C# methods."); - } - else if (runtimeHelpers.isPendingSynchronousCall) { - throw new Error("Cannot call synchronous C# method from inside a synchronous call to a JS method."); + if (monoThreadInfo.isUI) { + if (runtimeHelpers.config.jsThreadBlockingMode == JSThreadBlockingMode.PreventSynchronousJSExport) { + throw new Error("Cannot call synchronous C# methods."); + } + else if (runtimeHelpers.isPendingSynchronousCall) { + throw new Error("Cannot call synchronous C# method from inside a synchronous call to a JS method."); + } } if (runtimeHelpers.isManagedRunningOnCurrentThread) { twraps.mono_wasm_invoke_jsexport_sync(method, args as any); diff --git a/src/mono/browser/runtime/multi-threading.md b/src/mono/browser/runtime/multi-threading.md deleted file mode 100644 index e4b3985923d503..00000000000000 --- a/src/mono/browser/runtime/multi-threading.md +++ /dev/null @@ -1,52 +0,0 @@ -# Multi-threading with JavaScript interop - -## Meaningful configurations are: - - * Single-threaded mode as you know it since .Net 6 - - default, safe, tested, supported - - from .Net 8 it could be easily started also as a web worker, but you need your own messaging between main and worker - * `MainThreadingMode.DeputyThread` + `JSThreadBlockingMode.NoBlockingWait` + `JSThreadInteropMode.SimpleSynchronousJSInterop` - + **default threading**, safe, tested, supported - + blocking `.Wait` is allowed on thread pool and new threads - - blocking `.Wait` throws `PlatformNotSupportedException` on `JSWebWorker` and main thread - - DOM events like `onClick` need to be asynchronous, if the handler needs use synchronous `[JSImport]` - - synchronous calls to `[JSImport]`/`[JSExport]` can't synchronously call back - - * `MainThreadingMode.DeputyAndIOThreads` + `JSThreadBlockingMode.AllowBlockingWaitInAsyncCode` + `JSThreadInteropMode.SimpleSynchronousJSInterop` - + **default threading**, safe, tested, supported - + blocking `.Wait` is allowed on thread pool and new threads - - blocking `.Wait` throws `PlatformNotSupportedException` on `JSWebWorker` and main thread only when they are called from JS via synchronous `JSExport` - - DOM events like `onClick` need to be asynchronous, if the handler needs use synchronous `[JSImport]` - - synchronous calls to `[JSImport]`/`[JSExport]` can't synchronously call back - - * `MainThreadingMode.DeputyThread` + `JSThreadBlockingMode.AllowBlockingWait` + `JSThreadInteropMode.SimpleSynchronousJSInterop` - + pragmatic for legacy codebase, which contains blocking code and can't be fully executed on thread pool or new threads - - ** could cause deadlocks !!!** - - Use your own judgment before you opt in. - - blocking .Wait is allowed on all threads! - - blocking .Wait on pending JS `Task`/`Promise` (like HTTP/WS requests) could cause deadlocks! - - reason is that blocked thread can't process the browser event loop - - so it can't resolve the promises - - even when it's longer `Promise`/`Task` chain - - DOM events like `onClick` need to be asynchronous, if the handler needs use synchronous `[JSImport]` - - synchronous calls to `[JSImport]`/`[JSExport]` can't synchronously call back - -## Unsupported combinations are: - * `MainThreadingMode.DeputyThread` + `JSThreadBlockingMode.NoBlockingWait` + `JSThreadInteropMode.NoSyncJSInterop` - + very safe - - HTTP/WS requests are not possible because it currently uses synchronous JS interop - - Blazor doesn't work because it currently uses synchronous JS interop - * `MainThreadingMode.UIThread` - - not recommended, not tested, not supported! - - can deadlock on creating new threads - - can deadlock on blocking `.Wait` for a pending JS `Promise`/`Task`, including HTTP/WS requests - - .Wait is spin-waiting - it blocks debugger, network, UI rendering, ... - + JS interop to UI is faster, synchronous and re-entrant - -### There could be more JSThreadInteropModes: - - allow re-entrant synchronous JS interop on `JSWebWorker`. - - This is possible because managed code is running on same thread as JS. - - But it's nuanced to debug it, when things go wrong. - - allow re-entrant synchronous JS interop also on deputy thread. - - This is not possible for deputy, because it would deadlock on call back to different thread. - - The thread receiving the callback is still blocked waiting for the first synchronous call to finish. diff --git a/src/mono/browser/runtime/pthreads/index.ts b/src/mono/browser/runtime/pthreads/index.ts index 0a5911605282d0..b1fcba0d859204 100644 --- a/src/mono/browser/runtime/pthreads/index.ts +++ b/src/mono/browser/runtime/pthreads/index.ts @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +import { mono_log_warn } from "../logging"; +import { utf16ToString } from "../strings"; + export { mono_wasm_main_thread_ptr, mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop, mono_wasm_pthread_ptr, update_thread_info, isMonoThreadMessage, monoThreadInfo, @@ -18,3 +21,8 @@ export { export { mono_wasm_start_deputy_thread_async } from "./deputy-thread"; export { mono_wasm_start_io_thread_async } from "./io-thread"; + +export function mono_wasm_warn_about_blocking_wait(ptr: number, length: number) { + const warning = utf16ToString(ptr, ptr + length); + mono_log_warn(warning); +} \ No newline at end of file diff --git a/src/mono/browser/runtime/startup.ts b/src/mono/browser/runtime/startup.ts index 1ae17e43edf191..8580e5aca4b4b4 100644 --- a/src/mono/browser/runtime/startup.ts +++ b/src/mono/browser/runtime/startup.ts @@ -4,7 +4,7 @@ import WasmEnableThreads from "consts:wasmEnableThreads"; import BuildConfiguration from "consts:configuration"; -import { DotnetModuleInternal, CharPtrNull, MainThreadingMode } from "./types/internal"; +import { DotnetModuleInternal, CharPtrNull } from "./types/internal"; import { exportedRuntimeAPI, INTERNAL, loaderHelpers, Module, runtimeHelpers, createPromiseController, mono_assert } from "./globals"; import cwraps, { init_c_exports, threads_c_functions as tcwraps } from "./cwraps"; import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug"; @@ -274,19 +274,14 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) { mono_log_info("UI thread is alive!"); }, 3000); - if (WasmEnableThreads && - (runtimeHelpers.config.mainThreadingMode == MainThreadingMode.DeputyThread - || runtimeHelpers.config.mainThreadingMode == MainThreadingMode.DeputyAndIOThreads)) { + if (WasmEnableThreads) { // this will create thread and call start_runtime() on it runtimeHelpers.monoThreadInfo = monoThreadInfo; runtimeHelpers.isManagedRunningOnCurrentThread = false; update_thread_info(); runtimeHelpers.managedThreadTID = tcwraps.mono_wasm_create_deputy_thread(); runtimeHelpers.proxyGCHandle = await runtimeHelpers.afterMonoStarted.promise; - - if (WasmEnableThreads && runtimeHelpers.config.mainThreadingMode == MainThreadingMode.DeputyAndIOThreads) { - runtimeHelpers.ioThreadTID = tcwraps.mono_wasm_create_io_thread(); - } + runtimeHelpers.ioThreadTID = tcwraps.mono_wasm_create_io_thread(); // TODO make UI thread not managed tcwraps.mono_wasm_register_ui_thread(); @@ -301,9 +296,7 @@ async function onRuntimeInitializedAsync(userOnRuntimeInitialized: () => void) { await start_runtime(); } - if (WasmEnableThreads && runtimeHelpers.config.mainThreadingMode == MainThreadingMode.DeputyAndIOThreads) { - await runtimeHelpers.afterIOStarted.promise; - } + await runtimeHelpers.afterIOStarted.promise; runtimeList.registerRuntime(exportedRuntimeAPI); @@ -541,10 +534,7 @@ export async function start_runtime() { monoThreadInfo.isRegistered = true; runtimeHelpers.currentThreadTID = monoThreadInfo.pthreadId = runtimeHelpers.managedThreadTID = mono_wasm_pthread_ptr(); update_thread_info(); - runtimeHelpers.proxyGCHandle = install_main_synchronization_context( - runtimeHelpers.config.jsThreadBlockingMode!, - runtimeHelpers.config.jsThreadInteropMode!, - runtimeHelpers.config.mainThreadingMode!); + runtimeHelpers.proxyGCHandle = install_main_synchronization_context(runtimeHelpers.config.jsThreadBlockingMode!); runtimeHelpers.isManagedRunningOnCurrentThread = true; // start finalizer thread, lazy diff --git a/src/mono/browser/runtime/types/internal.ts b/src/mono/browser/runtime/types/internal.ts index 16967d26b9d299..22eaebf7545c1d 100644 --- a/src/mono/browser/runtime/types/internal.ts +++ b/src/mono/browser/runtime/types/internal.ts @@ -95,9 +95,7 @@ export type MonoConfigInternal = MonoConfig & { GitHash?: string, ProductVersion?: string, - mainThreadingMode?: MainThreadingMode, jsThreadBlockingMode?: JSThreadBlockingMode, - jsThreadInteropMode?: JSThreadInteropMode, }; export type RunArguments = { @@ -569,36 +567,37 @@ export interface MonoThreadMessage { cmd: string; } -// keep in sync with JSHostImplementation.Types.cs -export const enum MainThreadingMode { - // Running the managed main thread on UI thread. - // Managed GC and similar scenarios could be blocking the UI. - // Easy to deadlock. Not recommended for production. - UIThread = 0, - // Running the managed main thread on dedicated WebWorker. Marshaling all JavaScript calls to and from the main thread. - DeputyThread = 1, - // TODO comment - DeputyAndIOThreads = 2, -} - // keep in sync with JSHostImplementation.Types.cs export const enum JSThreadBlockingMode { - // throw PlatformNotSupportedException if blocking .Wait is called on threads with JS interop, like JSWebWorker and Main thread. - // Avoids deadlocks (typically with pending JS promises on the same thread) by throwing exceptions. - NoBlockingWait = 0, - // TODO comment - AllowBlockingWaitInAsyncCode = 1, - // allow .Wait on all threads. - // Could cause deadlocks with blocking .Wait on a pending JS Task/Promise on the same thread or similar Task/Promise chain. - AllowBlockingWait = 100, -} - -// keep in sync with JSHostImplementation.Types.cs -export const enum JSThreadInteropMode { - // throw PlatformNotSupportedException if synchronous JSImport/JSExport is called on threads with JS interop, like JSWebWorker and Main thread. - // calling synchronous JSImport on thread pool or new threads is allowed. - NoSyncJSInterop = 0, - // allow non-re-entrant synchronous blocking calls to and from JS on JSWebWorker on threads with JS interop, like JSWebWorker and Main thread. - // calling synchronous JSImport on thread pool or new threads is allowed. - SimpleSynchronousJSInterop = 1, + /** + * Prevents synchronous JSExport from being called from JavaScript code in UI thread. + * On JSWebWorker synchronous JSExport always works. + * On JSWebWorker blocking .Wait always warns. + * This is the default mode. + */ + PreventSynchronousJSExport = 0, + /** + * Allows synchronous JSExport to be called from JavaScript code also in UI thread. + * Inside of that call blocking .Wait throws PNSE. + * Inside of that call nested call back to synchronous JSImport throws PNSE (because it would deadlock otherwise in 100% cases). + * On JSWebWorker synchronous JSExport always works. + * On JSWebWorker blocking .Wait always throws PNSE. + */ + ThrowWhenBlockingWait = 1, + /** + * Allows synchronous JSExport to be called from JavaScript code also in UI thread. + * Inside of that call blocking .Wait warns. + * Inside of that call nested call back to synchronous JSImport throws PNSE (because it would deadlock otherwise in 100% cases). + * On JSWebWorker synchronous JSExport always works. + * On JSWebWorker blocking .Wait always warns. + */ + WarnWhenBlockingWait = 2, + /** + * Allows synchronous JSExport to be called from JavaScript code, and allows managed code to use blocking .Wait + * .Wait on Promise/Task chains could lead to deadlock because JS event loop is not processed and it can't resolve JS promises. + * This mode is dangerous and not supported. + * Allows synchronous JSExport to be called from JavaScript code also in Main thread. + * Inside of that call nested call back to synchronous JSImport throws PNSE (because it would deadlock otherwise in 100% cases). + */ + DangerousAllowBlockingWait = 100, } \ No newline at end of file diff --git a/src/mono/browser/test-main.js b/src/mono/browser/test-main.js index 3aacd8e2c67d68..c7403640ce51c0 100644 --- a/src/mono/browser/test-main.js +++ b/src/mono/browser/test-main.js @@ -252,7 +252,8 @@ function configureRuntime(dotnet, runArgs) { .withInteropCleanupOnExit() .withDumpThreadsOnNonZeroExit() .withConfig({ - loadAllSatelliteResources: true + loadAllSatelliteResources: true, + jsThreadBlockingMode: 1, /* ThrowWhenBlockingWait */ }); if (ENVIRONMENT_IS_NODE) { diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index cfd411c712c385..97ac4e1e2cea25 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -629,7 +629,6 @@ mono_wasm_register_ui_thread (void) MONO_ENTER_GC_SAFE_UNBALANCED; } -// TODO ideally we should not need to have UI thread registered as managed EMSCRIPTEN_KEEPALIVE void mono_wasm_register_io_thread (void) { diff --git a/src/mono/sample/wasm/browser-threads/main.js b/src/mono/sample/wasm/browser-threads/main.js index 127e2402f78542..8dbad8b1d9c995 100644 --- a/src/mono/sample/wasm/browser-threads/main.js +++ b/src/mono/sample/wasm/browser-threads/main.js @@ -17,6 +17,9 @@ try { .withElementOnExit() .withExitCodeLogging() .withExitOnUnhandledError() + .withConfig({ + jsThreadBlockingMode: 1, /* ThrowWhenBlockingWait */ + }) .create(); setModuleImports("main.js", {