From 19034d25046ed3d277b97282f08d1ad3d91ebb5a Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Thu, 21 Mar 2024 23:05:11 +0100 Subject: [PATCH] more --- .../System/Threading/LowLevelLifoSemaphore.cs | 3 ++ .../System/Threading/LowLevelMonitor.Unix.cs | 3 ++ .../System/Threading/ManualResetEventSlim.cs | 4 ++ .../src/System/Threading/WaitHandle.cs | 4 ++ .../WaitSubsystem.ThreadWaitInfo.Unix.cs | 3 ++ .../System/Threading/WaitSubsystem.Unix.cs | 3 ++ .../WaitSubsystem.WaitableObject.Unix.cs | 3 ++ .../JavaScript/WebWorkerTestBase.cs | 49 +++++++++++-------- 8 files changed, 52 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs index 7f7bddf24737b3..5e2cad24074914 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs @@ -40,6 +40,9 @@ public LowLevelLifoSemaphore(int initialSignalCount, int maximumSignalCount, int public bool Wait(int timeoutMs, bool spinWait) { Debug.Assert(timeoutMs >= -1); +#if FEATURE_WASM_MANAGED_THREADS + Thread.AssureBlockingPossible(); +#endif int spinCount = spinWait ? _spinCount : 0; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Unix.cs index 4b3dfb3be1cc4b..de7b4d64ae089e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Unix.cs @@ -41,6 +41,9 @@ private void ReleaseCore() private void WaitCore() { +#if FEATURE_WASM_MANAGED_THREADS + Thread.AssureBlockingPossible(); +#endif Interop.Sys.LowLevelMonitor_Wait(_nativeMonitor); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs index a385543f9174ab..516fb42bf0a52e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs @@ -485,6 +485,10 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) ArgumentOutOfRangeException.ThrowIfLessThan(millisecondsTimeout, -1); +#if FEATURE_WASM_MANAGED_THREADS + Thread.AssureBlockingPossible(); +#endif + if (!IsSet) { if (millisecondsTimeout == 0) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs index 21920bc39b754f..453ab002dd2664 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.cs @@ -112,6 +112,10 @@ internal bool WaitOneNoCheck( { Debug.Assert(millisecondsTimeout >= -1); +#if FEATURE_WASM_MANAGED_THREADS + Thread.AssureBlockingPossible(); +#endif + // The field value is modifiable via the public property, save it locally // to ensure that one instance is used in all places in this method SafeWaitHandle? waitHandle = _waitHandle; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs index 8bcafa15a6271b..78d32c67d0d331 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs @@ -278,6 +278,9 @@ private int ProcessSignaledWaitState() public int Wait(int timeoutMilliseconds, bool interruptible, bool isSleep, ref LockHolder lockHolder) { +#if FEATURE_WASM_MANAGED_THREADS + Thread.AssureBlockingPossible(); +#endif if (isSleep) { s_lock.VerifyIsNotLocked(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs index 4a349d8b303117..f930f4fe5437e1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs @@ -347,6 +347,9 @@ public static int Wait( Debug.Assert(waitHandles.Length > 0); Debug.Assert(waitHandles.Length <= WaitHandle.MaxWaitHandles); Debug.Assert(timeoutMilliseconds >= -1); +#if FEATURE_WASM_MANAGED_THREADS + Thread.AssureBlockingPossible(); +#endif ThreadWaitInfo waitInfo = Thread.CurrentThread.WaitInfo; WaitableObject?[] waitableObjects = waitInfo.GetWaitedObjectArray(waitHandles.Length); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs index fdf3ca54df23d5..e3bb6e1c823f80 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs @@ -307,6 +307,9 @@ public int Wait(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interrupt Debug.Assert(waitInfo.Thread == Thread.CurrentThread); Debug.Assert(timeoutMilliseconds >= -1); +#if FEATURE_WASM_MANAGED_THREADS + Thread.AssureBlockingPossible(); +#endif var lockHolder = new LockHolder(s_lock); try 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 dd76c3fa80c894..77aef0857a8d2e 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 @@ -168,35 +168,44 @@ static void LocalCtsIgnoringCall(Action action) public static IEnumerable BlockingCalls = new List { + // things that should NOT throw PNSE 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 = false, Name = "CancellationTokenSource.ctor", Call = delegate (CancellationToken ct) { + using var cts = new CancellationTokenSource(8); + }}, + new NamedCall { IsBlocking = false, Name = "Task.Delay", Call = delegate (CancellationToken ct) { + Task.Delay(30, ct); + }}, + new NamedCall { IsBlocking = false, Name = "new Timer", Call = delegate (CancellationToken ct) { + new Timer((_) => { }, null, 1, -1); + }}, + + // things which should throw PNSE on sync JSExport and JSWebWorker + new NamedCall { IsBlocking = true, Name = "Task.Wait", Call = delegate (CancellationToken ct) { Task.Delay(30, ct).Wait(ct); }}, + new NamedCall { IsBlocking = true, Name = "Task.WaitAll", Call = delegate (CancellationToken ct) { Task.WaitAll(Task.Delay(30, ct)); }}, + new NamedCall { IsBlocking = true, Name = "Task.WaitAny", Call = delegate (CancellationToken ct) { Task.WaitAny(Task.Delay(30, ct)); }}, new NamedCall { IsBlocking = true, Name = "ManualResetEventSlim.Wait", Call = delegate (CancellationToken ct) { - using var mr = new ManualResetEventSlim(false); + 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); + 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); - 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); + using var mr = new ManualResetEventSlim(false); + 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()