| File: System\Threading\Thread.NativeAot.Multithreading.cs | Web Access |
| Project: System.Private.CoreLib.csproj (System.Private.CoreLib) |
// 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.Runtime.ExceptionServices; using System.Runtime.InteropServices; namespace System.Threading { public sealed partial class Thread { private StartHelper? _startHelper; private Exception? _startException; partial void StartCore() { using (_lock.EnterScope()) { if (!GetThreadStateBit(ThreadState.Unstarted)) { throw new ThreadStateException(SR.ThreadState_AlreadyStarted); } bool waitingForThreadStart = false; GCHandle<Thread> threadHandle = new GCHandle<Thread>(this); try { if (!CreateThread(threadHandle)) { throw new OutOfMemoryException(); } // Skip cleanup if any asynchronous exception happens while waiting for the thread start waitingForThreadStart = true; // Wait until the new thread either dies or reports itself as started while (GetThreadStateBit(ThreadState.Unstarted) && !JoinInternal(0)) { Yield(); } waitingForThreadStart = false; } finally { Debug.Assert(!waitingForThreadStart, "Leaked threadHandle"); if (!waitingForThreadStart) { threadHandle.Dispose(); } } if (GetThreadStateBit(ThreadState.Unstarted)) { Exception? startException = _startException; _startException = null; throw new ThreadStartException(startException ?? new OutOfMemoryException()); } Debug.Assert(_startException == null); } } private static void StartThread(IntPtr parameter) { Thread thread = GCHandle<Thread>.FromIntPtr(parameter).Target; try { t_currentThread = thread; System.Threading.ManagedThreadId.SetForCurrentThread(thread._managedThreadId); thread.InitializeComOnNewThread(); } catch (Exception e) { thread._startException = e; #if !TARGET_WINDOWS // This should go away once OnThreadExit stops using t_currentThread to signal // shutdown of the thread on Unix. thread._stopped!.Set(); #endif // Terminate the current thread. The creator thread will throw a ThreadStartException. return; } // Report success to the creator thread, which will free threadHandle int state = thread.ClearThreadStateBit(ThreadState.Unstarted); if ((state & (int)ThreadState.Background) == 0) { IncrementRunningForeground(); } try { StartHelper? startHelper = thread._startHelper; Debug.Assert(startHelper is not null); thread._startHelper = null; startHelper.Run(); } catch (Exception ex) when (ExceptionHandling.IsHandledByGlobalHandler(ex)) { // the handler returned "true" means the exception is now "handled" and we should gracefully exit. } finally { thread.SetThreadStateBit(ThreadState.Stopped); } } } }