Repository: dotnet/runtime
File: src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs (C#)

Code before:
            [MethodImpl(MethodImplOptions.NoInlining)]
            static void PollGCWorker() => PollGCInternal();
        }

#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
        internal WaitSubsystem.ThreadWaitInfo WaitInfo
        {
            get
            {
                return Volatile.Read(ref _waitInfo) ?? AllocateWaitInfo();

                WaitSubsystem.ThreadWaitInfo AllocateWaitInfo()
                {
                    Interlocked.CompareExchange(ref _waitInfo, new WaitSubsystem.ThreadWaitInfo(this), null!);
                    return _waitInfo;
                }
            }
        }
#endif

        private void OnThreadExiting()
        {
            // Consider this managed thread as dead.
            // The unmanaged thread is still alive, but will die soon, after cleaning up some state.
            // We do this before OnThreadExiting and SetJoinHandle so that any threads
            // waiting on this thread to end will correctly see that it is stopped
            // when we set the join handle.
            _isDead = true;
#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
            // Inform the wait subsystem that the thread is exiting. For instance, this would abandon any mutexes locked by
            // the thread.
            _waitInfo?.OnThreadExiting();
            SetJoinHandle();
#endif
        }

        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_ReentrantWaitAny")]
        internal static unsafe partial int ReentrantWaitAny([MarshalAs(UnmanagedType.Bool)] bool alertable, int timeout, int count, IntPtr* handles);

        internal static void CheckForPendingInterrupt()
        {
            CheckForPendingInterrupt(CurrentThread.GetNativeHandle());
            GC.KeepAlive(CurrentThread);
        }

        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_CheckForPendingInterrupt")]
        private static partial void CheckForPendingInterrupt(ThreadHandle t);

        [StructLayout(LayoutKind.Sequential)]
        private struct NativeThreadClass
        {

Review comment (suggestion):
The comment states "We do this before OnThreadExiting and SetJoinHandle" but this code is already inside the OnThreadExiting method. The comment should be clarified to say something like "We do this before calling _waitInfo?.OnThreadExiting() and SetJoinHandle()" to avoid confusion, or be reworded to make it clear we're referring to the operations performed later in this method rather than the method itself.
```suggestion
            // We set _isDead = true before calling _waitInfo?.OnThreadExiting() and SetJoinHandle()
            // so that any threads waiting on this thread to end will correctly see that it is stopped
```

Code after:
                PollGCWorker();
            }

            [MethodImpl(MethodImplOptions.NoInlining)]
            static void PollGCWorker() => PollGCInternal();
        }

#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
        internal WaitSubsystem.ThreadWaitInfo WaitInfo
        {
            get
            {
                return Volatile.Read(ref _waitInfo) ?? AllocateWaitInfo();

                WaitSubsystem.ThreadWaitInfo AllocateWaitInfo()
                {
                    Interlocked.CompareExchange(ref _waitInfo, new WaitSubsystem.ThreadWaitInfo(this), null!);
                    return _waitInfo;
                }
            }
        }
#endif

        private void OnThreadExiting()
        {
            // Consider this managed thread as dead.
            // The unmanaged thread is still alive, but will die soon, after cleaning up some state.
            // We set _isDead = true before calling _waitInfo?.OnThreadExiting() and SetJoinHandle()
            // so that any threads waiting on this thread to end will correctly see that it is stopped
            // when we set the join handle.
            _isDead = true;
#if TARGET_UNIX || TARGET_BROWSER || TARGET_WASI
            // Inform the wait subsystem that the thread is exiting. For instance, this would abandon any mutexes locked by
            // the thread.
            _waitInfo?.OnThreadExiting();
            SetJoinHandle();
#endif
        }

        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_ReentrantWaitAny")]
        internal static unsafe partial int ReentrantWaitAny([MarshalAs(UnmanagedType.Bool)] bool alertable, int timeout, int count, IntPtr* handles);

        internal static void CheckForPendingInterrupt()
        {
            CheckForPendingInterrupt(CurrentThread.GetNativeHandle());
            GC.KeepAlive(CurrentThread);
        }

        [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ThreadNative_CheckForPendingInterrupt")]
        private static partial void CheckForPendingInterrupt(ThreadHandle t);