diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index 5e65109ddbb378..49b0e33a86f9b5 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -2657,7 +2657,7 @@
-
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.Unix.cs
index 3c5888a6f80dbd..c46c43604bb1df 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPool.Unix.cs
@@ -16,11 +16,9 @@ public static partial class ThreadPool
AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.EnableWorkerTracking", "DOTNET_ThreadPool_EnableWorkerTracking");
#endif
-#if !(TARGET_BROWSER && FEATURE_WASM_THREADS)
// Indicates whether the thread pool should yield the thread from the dispatch loop to the runtime periodically so that
// the runtime may use the thread for processing other work.
internal static bool YieldFromDispatchLoop => false;
-#endif
#if !CORECLR
internal static bool EnsureConfigInitialized() => true;
diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
index 81e577b690429f..ca865e7a856dad 100644
--- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -273,13 +273,10 @@
-
+
-
-
-
diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Browser.Threads.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Browser.Threads.Mono.cs
index 632b0c934ee4c0..cc3f606fe6273d 100644
--- a/src/mono/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Browser.Threads.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Browser.Threads.Mono.cs
@@ -7,7 +7,7 @@ internal sealed partial class PortableThreadPool
{
private static partial class WorkerThread
{
- private static bool IsIOPending => WebWorkerEventLoop.HasJavaScriptInteropDependents;
+ private static bool IsIOPending => false;
}
private struct CpuUtilizationReader
diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerThread.Browser.Threads.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerThread.Browser.Threads.Mono.cs
deleted file mode 100644
index b45dee7fa2fd6f..00000000000000
--- a/src/mono/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerThread.Browser.Threads.Mono.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Diagnostics.Tracing;
-using System.Runtime.CompilerServices;
-
-namespace System.Threading
-{
- internal sealed partial class PortableThreadPool
- {
- ///
- /// The worker thread infastructure for the CLR thread pool.
- ///
- private static partial class WorkerThread
- {
- ///
- /// Semaphore for controlling how many threads are currently working.
- ///
- private static readonly LowLevelLifoAsyncWaitSemaphore s_semaphore =
- new LowLevelLifoAsyncWaitSemaphore(
- 0,
- MaxPossibleThreadCount,
- AppContextConfigHelper.GetInt32Config(
- "System.Threading.ThreadPool.UnfairSemaphoreSpinLimit",
- SemaphoreSpinCountDefault,
- false),
- onWait: () =>
- {
- if (NativeRuntimeEventSource.Log.IsEnabled())
- {
- NativeRuntimeEventSource.Log.ThreadPoolWorkerThreadWait(
- (uint)ThreadPoolInstance._separated.counts.VolatileRead().NumExistingThreads);
- }
- });
-
- private static readonly ThreadStart s_workerThreadStart = WorkerThreadStart;
-
- private sealed record SemaphoreWaitState(PortableThreadPool ThreadPoolInstance, LowLevelLock ThreadAdjustmentLock, WebWorkerEventLoop.KeepaliveToken KeepaliveToken)
- {
- public bool SpinWait = true;
-
- public void ResetIteration() {
- SpinWait = true;
- }
- }
-
- private static void WorkerThreadStart()
- {
- Thread.CurrentThread.SetThreadPoolWorkerThreadName();
-
- PortableThreadPool threadPoolInstance = ThreadPoolInstance;
-
- if (NativeRuntimeEventSource.Log.IsEnabled())
- {
- NativeRuntimeEventSource.Log.ThreadPoolWorkerThreadStart(
- (uint)threadPoolInstance._separated.counts.VolatileRead().NumExistingThreads);
- }
-
- LowLevelLock threadAdjustmentLock = threadPoolInstance._threadAdjustmentLock;
- var keepaliveToken = WebWorkerEventLoop.KeepalivePush();
- SemaphoreWaitState state = new(threadPoolInstance, threadAdjustmentLock, keepaliveToken) { SpinWait = true };
- // set up the callbacks for semaphore waits, tell
- // emscripten to keep the thread alive, and return to
- // the JS event loop.
- WaitForWorkLoop(s_semaphore, state);
- // return from thread start with keepalive - the thread will stay alive in the JS event loop
- }
-
- private static readonly Action s_WorkLoopSemaphoreSuccess = new(WorkLoopSemaphoreSuccess);
- private static readonly Action s_WorkLoopSemaphoreTimedOut = new(WorkLoopSemaphoreTimedOut);
-
- private static void WaitForWorkLoop(LowLevelLifoAsyncWaitSemaphore semaphore, SemaphoreWaitState state)
- {
- semaphore.PrepareAsyncWait(ThreadPoolThreadTimeoutMs, s_WorkLoopSemaphoreSuccess, s_WorkLoopSemaphoreTimedOut, state);
- // thread should still be kept alive
- Debug.Assert(state.KeepaliveToken.Valid);
- }
-
- private static void WorkLoopSemaphoreSuccess(LowLevelLifoAsyncWaitSemaphore semaphore, object? stateObject)
- {
- SemaphoreWaitState state = (SemaphoreWaitState)stateObject!;
- WorkerDoWork(state.ThreadPoolInstance, ref state.SpinWait);
- // Go around the loop one more time, keeping existing mutated state
- WaitForWorkLoop(semaphore, state);
- }
-
- private static void WorkLoopSemaphoreTimedOut(LowLevelLifoAsyncWaitSemaphore semaphore, object? stateObject)
- {
- SemaphoreWaitState state = (SemaphoreWaitState)stateObject!;
- if (ShouldExitWorker(state.ThreadPoolInstance, state.ThreadAdjustmentLock)) {
- // we're done, kill the thread.
-
- // we're wrapped in an emscripten eventloop handler which will consult the
- // keepalive count, destroy the thread and run the TLS dtor which will
- // unregister the thread from Mono
- state.KeepaliveToken.Pop();
- return;
- } else {
- // more work showed up while we were shutting down, go around one more time
- state.ResetIteration();
- WaitForWorkLoop(semaphore, state);
- }
- }
-
- private static void CreateWorkerThread()
- {
- // Thread pool threads must start in the default execution context without transferring the context, so
- // using captureContext: false.
- Thread workerThread = new Thread(s_workerThreadStart);
- workerThread.IsThreadPoolThread = true;
- workerThread.IsBackground = true;
- // thread name will be set in thread proc
-
- // This thread will return to the JS event loop - tell the runtime not to cleanup
- // after the start function returns, if the Emscripten keepalive is non-zero.
- WebWorkerEventLoop.StartExitable(workerThread, captureContext: false);
- }
- }
- }
-}
diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Browser.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Browser.Mono.cs
index 406c5efcba46ec..78d45c30192ede 100644
--- a/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Browser.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Browser.Mono.cs
@@ -14,7 +14,7 @@
namespace System.Threading
{
#if FEATURE_WASM_THREADS
-#error when compiled with FEATURE_WASM_THREADS, we use PortableThreadPool.WorkerThread.Browser.Threads.Mono.cs
+#error when compiled with FEATURE_WASM_THREADS, we use normal unix thread pool
#endif
[System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")]
public sealed class RegisteredWaitHandle : MarshalByRefObject
diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Browser.Threads.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Browser.Threads.Mono.cs
deleted file mode 100644
index 7933e49db422b9..00000000000000
--- a/src/mono/System.Private.CoreLib/src/System/Threading/ThreadPool.Browser.Threads.Mono.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Threading
-{
- public static partial class ThreadPool
- {
- // Indicates that the threadpool should yield the thread from the dispatch loop to the
- // runtime periodically. We use this to return back to the JS event loop so that the JS
- // event queue can be drained
- internal static bool YieldFromDispatchLoop => true;
- }
-}
diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/WebWorkerEventLoop.Browser.Threads.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/WebWorkerEventLoop.Browser.Threads.Mono.cs
deleted file mode 100644
index 73c2959293d525..00000000000000
--- a/src/mono/System.Private.CoreLib/src/System/Threading/WebWorkerEventLoop.Browser.Threads.Mono.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics.CodeAnalysis;
-using System.Diagnostics.Tracing;
-using System.Runtime.CompilerServices;
-
-namespace System.Threading;
-
-///
-/// Keep a pthread alive in its WebWorker after its pthread start function returns.
-///
-internal static class WebWorkerEventLoop
-{
- // FIXME: these keepalive calls could be qcalls with a SuppressGCTransitionAttribute
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void KeepalivePushInternal();
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void KeepalivePopInternal();
-
- ///
- /// A keepalive token prevents a thread from shutting down even if it returns to the JS event
- /// loop. A thread may want a keepalive token if it needs to allow JS code to run to settle JS
- /// promises or execute JS timeout callbacks.
- ///
- internal sealed class KeepaliveToken
- {
- public bool Valid {get; private set; }
-
- private KeepaliveToken() { Valid = true; }
-
- ///
- /// Decrement the Emscripten keepalive count. A thread with a zero keepalive count will
- /// terminate when it returns from its start function or from an async invocation from the
- /// JS event loop.
- ///
- internal void Pop() {
- if (!Valid)
- throw new InvalidOperationException();
- Valid = false;
- KeepalivePopInternal();
- }
-
- internal static KeepaliveToken Create()
- {
- KeepalivePushInternal();
- return new KeepaliveToken();
- }
- }
-
- ///
- /// Increment the Emscripten keepalive count. A thread with a positive keepalive can return from its
- /// thread start function or a JS event loop invocation and continue running in the JS event
- /// loop.
- ///
- internal static KeepaliveToken KeepalivePush() => KeepaliveToken.Create();
-
- ///
- /// Start a thread that may be kept alive on its webworker after the start function returns,
- /// if the emscripten keepalive count is positive. Once the thread returns to the JS event
- /// loop it will be able to settle JS promises as well as run any queued managed async
- /// callbacks.
- ///
- internal static void StartExitable(Thread thread, bool captureContext)
- {
- // don't support captureContext == true, for now, since it's
- // not needed by PortableThreadPool.WorkerThread
- if (captureContext)
- throw new InvalidOperationException();
- // for now, threadpool threads are exitable, and nothing else is.
- if (!thread.IsThreadPoolThread)
- throw new InvalidOperationException();
- thread.HasExternalEventLoop = true;
- thread.UnsafeStart();
- }
-
- /// returns true if the current thread has unsettled JS Interop promises
- private static bool HasUnsettledInteropPromises => HasUnsettledInteropPromisesNative();
-
- // FIXME: this could be a qcall with a SuppressGCTransitionAttribute
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool HasUnsettledInteropPromisesNative();
-
- /// returns true if the current WebWorker has JavaScript objects that depend on the
- /// current managed thread.
- ///
- /// If this returns false, the runtime is allowed to allow the current managed thread
- /// to exit and for the WebWorker to be recycled by Emscripten for another managed
- /// thread.
- internal static bool HasJavaScriptInteropDependents
- {
- //
- // FIXME:
- // https://github.com/dotnet/runtime/issues/85052 - unsettled promises are not the only relevant
- // reasons for keeping a worker thread alive. We will need to add other conditions here.
- get => HasUnsettledInteropPromises;
- }
-}
diff --git a/src/mono/mono/metadata/icall-decl.h b/src/mono/mono/metadata/icall-decl.h
index 704092c5a47c17..0e51652955423d 100644
--- a/src/mono/mono/metadata/icall-decl.h
+++ b/src/mono/mono/metadata/icall-decl.h
@@ -191,10 +191,6 @@ ICALL_EXPORT void ves_icall_System_Threading_LowLevelLifoSemaphore_ReleaseIn
#if (defined(HOST_BROWSER) && !defined(DISABLE_THREADS)) || (defined(TARGET_WASM) && defined(ENABLE_ICALL_SYMBOL_MAP))
ICALL_EXPORT gpointer ves_icall_System_Threading_LowLevelLifoAsyncWaitSemaphore_InitInternal (void);
ICALL_EXPORT void ves_icall_System_Threading_LowLevelLifoAsyncWaitSemaphore_PrepareAsyncWaitInternal (gpointer sem_ptr, gint32 timeout_ms, gpointer success_cb, gpointer timeout_cb, intptr_t user_data);
-
-ICALL_EXPORT MonoBoolean ves_icall_System_Threading_WebWorkerEventLoop_HasUnsettledInteropPromisesNative(void);
-ICALL_EXPORT void ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePushInternal (void);
-ICALL_EXPORT void ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePopInternal (void);
#endif
#ifdef TARGET_AMD64
diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h
index b18d285c421ca0..abd46d5a39ce82 100644
--- a/src/mono/mono/metadata/icall-def.h
+++ b/src/mono/mono/metadata/icall-def.h
@@ -610,14 +610,6 @@ HANDLES(THREAD_10, "SetState", ves_icall_System_Threading_Thread_SetState, void,
HANDLES(THREAD_13, "StartInternal", ves_icall_System_Threading_Thread_StartInternal, void, 2, (MonoThreadObject, gint32))
NOHANDLES(ICALL(THREAD_14, "YieldInternal", ves_icall_System_Threading_Thread_YieldInternal))
-/* include these icalls if we're in the threaded wasm runtime, or if we're building a wasm-targeting cross compiler and we need to support --print-icall-table */
-#if (defined(HOST_BROWSER) && !defined(DISABLE_THREADS)) || (defined(TARGET_WASM) && defined(ENABLE_ICALL_SYMBOL_MAP))
-ICALL_TYPE(WEBWORKERLOOP, "System.Threading.WebWorkerEventLoop", WEBWORKERLOOP_1)
-NOHANDLES(ICALL(WEBWORKERLOOP_1, "HasUnsettledInteropPromisesNative", ves_icall_System_Threading_WebWorkerEventLoop_HasUnsettledInteropPromisesNative))
-NOHANDLES(ICALL(WEBWORKERLOOP_2, "KeepalivePopInternal", ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePopInternal))
-NOHANDLES(ICALL(WEBWORKERLOOP_3, "KeepalivePushInternal", ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePushInternal))
-#endif
-
ICALL_TYPE(TYPE, "System.Type", TYPE_1)
HANDLES(TYPE_1, "internal_from_handle", ves_icall_System_Type_internal_from_handle, MonoReflectionType, 1, (MonoType_ref))
diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c
index dbed9f92e7f883..6f3621af9d051e 100644
--- a/src/mono/mono/metadata/threads.c
+++ b/src/mono/mono/metadata/threads.c
@@ -4958,26 +4958,6 @@ ves_icall_System_Threading_LowLevelLifoAsyncWaitSemaphore_PrepareAsyncWaitIntern
mono_lifo_semaphore_asyncwait_prepare_wait (sem, timeout_ms, (LifoSemaphoreAsyncWaitCallbackFn)success_cb, (LifoSemaphoreAsyncWaitCallbackFn)timedout_cb, user_data);
}
-void
-ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePushInternal (void)
-{
- emscripten_runtime_keepalive_push();
-}
-
-void
-ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePopInternal (void)
-{
- emscripten_runtime_keepalive_pop();
-}
-
-extern int mono_wasm_eventloop_has_unsettled_interop_promises(void);
-
-MonoBoolean
-ves_icall_System_Threading_WebWorkerEventLoop_HasUnsettledInteropPromisesNative(void)
-{
- return !!mono_wasm_eventloop_has_unsettled_interop_promises();
-}
-
#endif /* HOST_BROWSER && !DISABLE_THREADS */
/* for the AOT cross compiler with --print-icall-table these don't need to be callable, they just
@@ -4995,22 +4975,5 @@ ves_icall_System_Threading_LowLevelLifoAsyncWaitSemaphore_PrepareAsyncWaitIntern
g_assert_not_reached ();
}
-void
-ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePushInternal (void)
-{
- g_assert_not_reached();
-}
-
-void
-ves_icall_System_Threading_WebWorkerEventLoop_KeepalivePopInternal (void)
-{
- g_assert_not_reached();
-}
-
-MonoBoolean
-ves_icall_System_Threading_WebWorkerEventLoop_HasUnsettledInteropPromisesNative(void)
-{
- g_assert_not_reached();
-}
#endif /* defined(TARGET_WASM) && defined(ENABLE_ICALL_SYMBOL_MAP) */
diff --git a/src/mono/sample/wasm/browser-threads-minimal/main.js b/src/mono/sample/wasm/browser-threads-minimal/main.js
index 72631334586fb6..329a45aa99b429 100644
--- a/src/mono/sample/wasm/browser-threads-minimal/main.js
+++ b/src/mono/sample/wasm/browser-threads-minimal/main.js
@@ -12,9 +12,6 @@ try {
const { getAssemblyExports, runMain } = await dotnet
//.withEnvironmentVariable("MONO_LOG_LEVEL", "debug")
//.withDiagnosticTracing(true)
- .withConfig({
- pthreadPoolSize: 6,
- })
.withElementOnExit()
.withExitCodeLogging()
.create();