Skip to content

Commit

Permalink
[mono] More Threading changes (#49637)
Browse files Browse the repository at this point in the history
* Move CurrentOSThreadId to shared

* Set t_currentThread in managed

* Remove native abandon_mutexes calls

Abandoning in managed seems to work fine

* Switch to managed Sleep

* Remove threads shutting_down state

* Remove more domain usage

* Move some files to shared per feedback

* Re-add shutting_down flag

* Eliminate helper method for timeout verification

* Remove argument validation in ThreadNative::Sleep

* Abandon mutexes on finalizer thread

* Rename to thread_exiting

* Move OnThreadExiting to Thread

* Fix build

* Build build part 2

* Switch to DynamicDependency

* Avoid calling managed while holding a lock

* Don't leak gchandles

* Clean up rebase

* Pt 2
  • Loading branch information
CoffeeFlux authored Apr 6, 2021
1 parent 0be8b88 commit 457f58c
Show file tree
Hide file tree
Showing 17 changed files with 172 additions and 184 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ private void StartCallback()
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void SleepInternal(int millisecondsTimeout);

public static void Sleep(int millisecondsTimeout) => SleepInternal(millisecondsTimeout);

[DllImport(RuntimeHelpers.QCall)]
internal static extern void UninterruptibleSleep0();

Expand Down Expand Up @@ -221,9 +219,6 @@ public ThreadPriority Priority
[MethodImpl(MethodImplOptions.InternalCall)]
private extern void SetPriorityNative(int priority);

/// <summary>Returns the operating system identifier for the current thread.</summary>
internal static ulong CurrentOSThreadId => GetCurrentOSThreadId();

[DllImport(RuntimeHelpers.QCall)]
private static extern ulong GetCurrentOSThreadId();

Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/vm/comsynchronizable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,10 +466,6 @@ FCIMPL1(void, ThreadNative::Sleep, INT32 iTime)

HELPER_METHOD_FRAME_BEGIN_0();

// validate the sleep time
if ((iTime < 0) && (iTime != INFINITE_TIMEOUT))
COMPlusThrowArgumentOutOfRange(W("millisecondsTimeout"), W("ArgumentOutOfRange_NeedNonNegOrNegative1"));

GetThread()->UserSleep(iTime);

HELPER_METHOD_FRAME_END();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1998,6 +1998,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\RegisteredWaitHandle.Portable.cs" />
</ItemGroup>
<ItemGroup Condition="'$(FeatureCoreCLR)' != 'true' and ('$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true')">
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeWaitHandle.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventWaitHandle.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Mutex.Unix.cs" />
Expand All @@ -2009,6 +2010,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitSubsystem.WaitableObject.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(FeatureCoreCLR)' != 'true' and '$(TargetsWindows)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitHandle.Windows.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.GetLastError.cs">
<Link>Interop\Windows\Kernel32\Interop.GetLastError.cs</Link>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
using System.Runtime;
using System.Runtime.InteropServices;

namespace System.Threading
{
public sealed partial class Thread
{
internal static void UninterruptibleSleep0() => WaitSubsystem.UninterruptibleSleep0();

private static void SleepInternal(int millisecondsTimeout) => WaitSubsystem.Sleep(millisecondsTimeout);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace System.Threading
{
public sealed partial class Thread
{
internal static void UninterruptibleSleep0() => Interop.Kernel32.Sleep(0);

private static void SleepInternal(int millisecondsTimeout)
{
Debug.Assert(millisecondsTimeout >= -1);
Interop.Kernel32.Sleep((uint)millisecondsTimeout);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,17 @@ public static Thread CurrentThread
}
}

[MethodImpl(MethodImplOptions.NoInlining)] // Slow path method. Make sure that the caller frame does not pay for PInvoke overhead.
public static void Sleep(int millisecondsTimeout)
{
if (millisecondsTimeout < Timeout.Infinite)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), millisecondsTimeout, SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
SleepInternal(millisecondsTimeout);
}

/// <summary>Returns the operating system identifier for the current thread.</summary>
internal static ulong CurrentOSThreadId => GetCurrentOSThreadId();

public ExecutionContext? ExecutionContext => ExecutionContext.Capture();

public string? Name
Expand Down
39 changes: 12 additions & 27 deletions src/mono/System.Private.CoreLib/src/System/Threading/Thread.Mono.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,9 @@ private Thread()

~Thread()
{
#if TARGET_UNIX || TARGET_BROWSER
_waitInfo?.OnThreadExiting();
#endif
FreeInternal();
}

internal static ulong CurrentOSThreadId
{
get
{
return GetCurrentOSThreadId();
}
}

public bool IsAlive
{
get
Expand Down Expand Up @@ -211,6 +200,7 @@ public bool Join(int millisecondsTimeout)

#if TARGET_UNIX || TARGET_BROWSER
[MemberNotNull(nameof(_waitInfo))]
[DynamicDependency(nameof(OnThreadExiting))]
#endif
private void Initialize()
{
Expand All @@ -237,16 +227,6 @@ public static void SpinWait(int iterations)
SpinWait_nop();
}

public static void Sleep(int millisecondsTimeout)
{
if (millisecondsTimeout < Timeout.Infinite)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), millisecondsTimeout, SR.ArgumentOutOfRange_NeedNonNegOrNegative1);

SleepInternal(millisecondsTimeout, true);
}

internal static void UninterruptibleSleep0() => SleepInternal(0, false);

// Called from the runtime
internal void StartCallback()
{
Expand Down Expand Up @@ -320,6 +300,13 @@ internal void ClearWaitSleepJoinState()
ClrState(this, ThreadState.WaitSleepJoin);
}

private static void OnThreadExiting(Thread thread)
{
#if TARGET_UNIX || TARGET_BROWSER
thread.WaitInfo.OnThreadExiting();
#endif
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern ulong GetCurrentOSThreadId();

Expand All @@ -328,15 +315,16 @@ internal void ClearWaitSleepJoinState()
private static extern void InitInternal(Thread thread);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void InitializeCurrentThread_icall([NotNull] ref Thread? thread);
private static extern Thread GetCurrentThread();

[MethodImpl(MethodImplOptions.NoInlining)]
private static Thread InitializeCurrentThread()
{
InitializeCurrentThread_icall(ref t_currentThread);
var current = GetCurrentThread();
#if TARGET_UNIX || TARGET_BROWSER
t_currentThread.EnsureWaitInfo();
current.EnsureWaitInfo();
#endif
t_currentThread = current;
return t_currentThread;
}

Expand Down Expand Up @@ -367,9 +355,6 @@ private static unsafe void SetName(Thread thread, string? name)
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool YieldInternal();

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void SleepInternal(int millisecondsTimeout, bool allowInterruption);

[Intrinsic]
private static void SpinWait_nop()
{
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/metadata/domain-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ mono_runtime_register_runtimeconfig_json_properties (MonovmRuntimeConfigArgument
void
mono_runtime_install_appctx_properties (void);

gboolean
mono_domain_set_fast (MonoDomain *domain, gboolean force);
void
mono_domain_set_fast (MonoDomain *domain);

G_END_DECLS

Expand Down
5 changes: 2 additions & 3 deletions src/mono/mono/metadata/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,13 +547,12 @@ mono_domain_unset (void)
SET_APPDOMAIN (NULL);
}

gboolean
mono_domain_set_fast (MonoDomain *domain, gboolean force)
void
mono_domain_set_fast (MonoDomain *domain)
{
MONO_REQ_GC_UNSAFE_MODE;

mono_domain_set_internal_with_options (domain, TRUE);
return TRUE;
}

void
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/metadata/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,8 @@ mono_runtime_do_background_work (void)
{
mono_threads_perform_thread_dump ();

mono_threads_exiting ();

finalize_domain_objects ();

MONO_PROFILER_RAISE (gc_finalizing, ());
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/icall-decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ ICALL_EXPORT MonoBoolean ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (const g
ICALL_EXPORT MonoBoolean ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char*, MonoAssemblyName*, MonoBoolean*, MonoBoolean* is_token_defined_arg);
ICALL_EXPORT MonoBoolean ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void);
ICALL_EXPORT MonoBoolean ves_icall_System_Threading_Thread_YieldInternal (void);
ICALL_EXPORT void ves_icall_System_Threading_Thread_GetCurrentThread (MonoThread * volatile *);
ICALL_EXPORT MonoThread *ves_icall_System_Threading_Thread_GetCurrentThread (void);
ICALL_EXPORT void ves_icall_System_ArgIterator_Setup (MonoArgIterator*, char*, char*);
ICALL_EXPORT MonoType* ves_icall_System_ArgIterator_IntGetNextArgType (MonoArgIterator*);
ICALL_EXPORT void ves_icall_System_ArgIterator_IntGetNextArg (MonoArgIterator*, MonoTypedRef*);
Expand Down
3 changes: 1 addition & 2 deletions src/mono/mono/metadata/icall-def-netcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,15 +487,14 @@ HANDLES(THREAD_1, "ClrState", ves_icall_System_Threading_Thread_ClrState, void,
HANDLES(ITHREAD_2, "FreeInternal", ves_icall_System_Threading_InternalThread_Thread_free_internal, void, 1, (MonoInternalThread))
HANDLES(THREAD_15, "GetCurrentOSThreadId", ves_icall_System_Threading_Thread_GetCurrentOSThreadId, guint64, 0, ())
HANDLES(THREAD_16, "GetCurrentProcessorNumber", ves_icall_System_Threading_Thread_GetCurrentProcessorNumber, gint32, 0, ())
NOHANDLES(ICALL(THREAD_5, "GetCurrentThread", ves_icall_System_Threading_Thread_GetCurrentThread))
HANDLES(THREAD_3, "GetState", ves_icall_System_Threading_Thread_GetState, guint32, 1, (MonoInternalThread))
HANDLES(THREAD_4, "InitInternal", ves_icall_System_Threading_Thread_InitInternal, void, 1, (MonoThreadObject))
NOHANDLES(ICALL(THREAD_5, "InitializeCurrentThread_icall", ves_icall_System_Threading_Thread_GetCurrentThread))
HANDLES(THREAD_6, "InterruptInternal", ves_icall_System_Threading_Thread_Interrupt_internal, void, 1, (MonoThreadObject))
HANDLES(THREAD_7, "JoinInternal", ves_icall_System_Threading_Thread_Join_internal, MonoBoolean, 2, (MonoThreadObject, int))
HANDLES(THREAD_8, "SetName_icall", ves_icall_System_Threading_Thread_SetName_icall, void, 3, (MonoInternalThread, const_gunichar2_ptr, gint32))
HANDLES(THREAD_9, "SetPriority", ves_icall_System_Threading_Thread_SetPriority, void, 2, (MonoThreadObject, int))
HANDLES(THREAD_10, "SetState", ves_icall_System_Threading_Thread_SetState, void, 2, (MonoInternalThread, guint32))
HANDLES(THREAD_11, "SleepInternal", ves_icall_System_Threading_Thread_Sleep_internal, void, 2, (gint32, MonoBoolean))
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))

Expand Down
9 changes: 6 additions & 3 deletions src/mono/mono/metadata/threads-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,11 @@ mono_threads_attach_coop (MonoDomain *domain, gpointer *dummy);
MONO_API void
mono_threads_detach_coop (gpointer cookie, gpointer *dummy);

MonoDomain*
mono_threads_attach_coop_internal (MonoDomain *domain, gpointer *cookie, MonoStackData *stackdata);
void
mono_threads_attach_coop_internal (gpointer *cookie, MonoStackData *stackdata);

void
mono_threads_detach_coop_internal (MonoDomain *orig_domain, gpointer cookie, MonoStackData *stackdata);
mono_threads_detach_coop_internal (gpointer cookie, MonoStackData *stackdata);

void mono_threads_begin_abort_protected_block (void);
gboolean mono_threads_end_abort_protected_block (void);
Expand Down Expand Up @@ -461,6 +461,9 @@ mono_threads_summarize_execute (MonoContext *ctx, gchar **out, MonoStackHash *ha
gboolean
mono_threads_summarize_one (MonoThreadSummary *out, MonoContext *ctx);

void
mono_threads_exiting (void);

#if SIZEOF_VOID_P == 4
/* Spin lock for unaligned InterlockedXXX 64 bit functions on 32bit platforms. */
extern mono_mutex_t mono_interlocked_mutex;
Expand Down
Loading

0 comments on commit 457f58c

Please sign in to comment.