1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System
.Globalization
;
6 using System
.Runtime
.CompilerServices
;
7 using System
.Runtime
.InteropServices
;
9 namespace System
.Threading
12 // Under netcore, there is only one thread object per thread
14 [StructLayout (LayoutKind
.Sequential
)]
17 #pragma warning disable 169, 414, 649
18 #region Sync with metadata/object-internals.h and InternalThread in mcs/class/corlib/System.Threading/Thread.cs
20 // stores a thread handle
22 IntPtr native_handle
; // used only on Win32
23 /* accessed only from unmanaged code */
25 private int name_free
; // bool
26 private int name_length
;
27 private ThreadState state
;
28 private object abort_exc
;
29 private int abort_state_handle
;
30 /* thread_id is only accessed from unmanaged code */
31 internal Int64 thread_id
;
32 private IntPtr debugger_thread
; // FIXME switch to bool as soon as CI testing with corlib version bump works
33 private UIntPtr static_data
; /* GC-tracked */
34 private IntPtr runtime_thread_info
;
35 /* current System.Runtime.Remoting.Contexts.Context instance
36 keep as an object to avoid triggering its class constructor when not needed */
37 private object current_appcontext
;
38 private object root_domain_thread
;
39 internal byte[] _serialized_principal
;
40 internal int _serialized_principal_version
;
41 private IntPtr appdomain_refs
;
42 private int interruption_requested
;
43 private IntPtr longlived
;
44 internal bool threadpool_thread
;
45 private bool thread_interrupt_requested
;
46 /* These are used from managed code */
47 internal int stack_size
;
48 internal byte apartment_state
;
49 internal volatile int critical_region_level
;
50 internal int managed_id
;
52 private IntPtr manage_callback
;
54 private IntPtr thread_pinning_ref
;
55 private IntPtr abort_protected_block_count
;
57 private IntPtr owned_mutex
;
58 private IntPtr suspended_event
;
59 private int self_suspended
;
60 private IntPtr thread_state
;
63 private object pending_exception
;
64 private object start_obj
;
66 /* This is used only to check that we are in sync between the representation
67 * of MonoInternalThread in native and InternalThread in managed
69 * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */
72 #pragma warning restore 169, 414, 649
77 CultureInfo culture
, ui_culture
;
78 internal ExecutionContext _executionContext
;
79 internal SynchronizationContext _synchronizationContext
;
91 internal static ulong CurrentOSThreadId
{
93 return GetCurrentOSThreadId ();
99 var state
= GetState (this);
100 return (state
& (ThreadState
.Unstarted
| ThreadState
.Stopped
| ThreadState
.Aborted
)) == 0;
104 public bool IsBackground
{
106 var state
= ValidateThreadState ();
107 return (state
& ThreadState
.Background
) != 0;
110 ValidateThreadState ();
112 SetState (this, ThreadState
.Background
);
114 ClrState (this, ThreadState
.Background
);
119 public bool IsThreadPoolThread
{
121 ValidateThreadState ();
122 return threadpool_thread
;
125 threadpool_thread
= value;
129 public int ManagedThreadId
=> managed_id
;
131 internal static int OptimalMaxSpinWaitsPerSpinIteration
{
133 // Default from coreclr (src/utilcode/yieldprocessornormalized.cpp)
138 public ThreadPriority Priority
{
140 ValidateThreadState ();
141 return (ThreadPriority
) priority
;
144 // TODO: arguments check
145 SetPriority (this, (int) value);
149 public ThreadState ThreadState
=> GetState (this);
151 void Create (ThreadStart start
) => SetStartHelper ((Delegate
) start
, 0); // 0 will setup Thread with default stackSize
153 void Create (ThreadStart start
, int maxStackSize
) => SetStartHelper ((Delegate
) start
, maxStackSize
);
155 void Create (ParameterizedThreadStart start
) => SetStartHelper ((Delegate
) start
, 0);
157 void Create (ParameterizedThreadStart start
, int maxStackSize
) => SetStartHelper ((Delegate
) start
, maxStackSize
);
159 public ApartmentState
GetApartmentState () => ApartmentState
.Unknown
;
161 public void DisableComObjectEagerCleanup ()
166 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
167 extern static int GetCurrentProcessorNumber ();
169 public static int GetCurrentProcessorId ()
171 int id
= GetCurrentProcessorNumber ();
174 id
= Environment
.CurrentManagedThreadId
;
179 public void Interrupt ()
181 InterruptInternal (this);
184 public bool Join (int millisecondsTimeout
)
186 if (millisecondsTimeout
< Timeout
.Infinite
)
187 throw new ArgumentOutOfRangeException (nameof (millisecondsTimeout
), millisecondsTimeout
, SR
.ArgumentOutOfRange_NeedNonNegOrNegative1
);
188 return JoinInternal (this, millisecondsTimeout
);
191 internal void ResetThreadPoolThread ()
196 if ((state
& ThreadState
.Background
) == 0)
199 if ((ThreadPriority
) priority
!= ThreadPriority
.Normal
)
200 Priority
= ThreadPriority
.Normal
;
203 void SetCultureOnUnstartedThreadNoCheck (CultureInfo
value, bool uiCulture
)
211 void SetStartHelper (Delegate start
, int maxStackSize
)
214 stack_size
= maxStackSize
;
217 public static void SpinWait (int iterations
)
222 while (iterations
-- > 0)
226 public static void Sleep (int millisecondsTimeout
)
228 if (millisecondsTimeout
< Timeout
.Infinite
)
229 throw new ArgumentOutOfRangeException (nameof (millisecondsTimeout
), millisecondsTimeout
, SR
.ArgumentOutOfRange_NeedNonNegOrNegative1
);
231 SleepInternal (millisecondsTimeout
, true);
234 internal static void UninterruptibleSleep0 () => SleepInternal (0, false);
238 StartInternal (this);
241 public void Start (object parameter
)
243 if (m_start
is ThreadStart
)
244 throw new InvalidOperationException (SR
.InvalidOperation_ThreadWrongThreadStart
);
246 m_start_arg
= parameter
;
247 StartInternal (this);
250 // Called from the runtime
251 internal void StartCallback ()
254 CurrentCulture
= culture
;
255 if (ui_culture
!= null)
256 CurrentUICulture
= ui_culture
;
257 if (m_start
is ThreadStart del
) {
261 var pdel
= (ParameterizedThreadStart
) m_start
;
262 var arg
= m_start_arg
;
269 partial void ThreadNameChanged (string value)
271 // TODO: Should only raise the events
272 SetName (this, value);
275 public static bool Yield ()
277 return YieldInternal ();
280 bool TrySetApartmentStateUnchecked (ApartmentState state
) => state
== ApartmentState
.Unknown
;
282 ThreadState
ValidateThreadState ()
284 var state
= GetState (this);
285 if ((state
& ThreadState
.Stopped
) != 0)
286 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
290 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
291 private extern static ulong GetCurrentOSThreadId ();
293 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
294 extern static void InitInternal (Thread thread
);
296 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
297 private extern static void InitializeCurrentThread_icall (ref Thread thread
);
299 [MethodImpl (MethodImplOptions
.NoInlining
)]
300 static Thread
InitializeCurrentThread () {
301 Thread thread
= null;
302 InitializeCurrentThread_icall (ref thread
);
306 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
307 extern void FreeInternal ();
309 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
310 extern static ThreadState
GetState (Thread thread
);
312 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
313 extern static void SetState (Thread thread
, ThreadState
set);
315 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
316 extern static void ClrState (Thread thread
, ThreadState clr
);
318 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
319 extern static string GetName (Thread thread
);
321 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
322 private static unsafe extern void SetName_icall (Thread thread
, char *name
, int nameLength
);
324 static unsafe void SetName (Thread thread
, String name
)
326 fixed (char* fixed_name
= name
)
327 SetName_icall (thread
, fixed_name
, name
?.Length
?? 0);
330 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
331 extern static bool YieldInternal ();
333 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
334 extern static void SleepInternal (int millisecondsTimeout
, bool allowInterruption
);
337 static void SpinWait_nop ()
341 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
342 extern static Thread
CreateInternal ();
344 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
345 extern static void StartInternal (Thread runtime_thread
);
347 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
348 extern static bool JoinInternal (Thread thread
, int millisecondsTimeout
);
350 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
351 extern static void InterruptInternal (Thread thread
);
353 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
354 extern static void SetPriority (Thread thread
, int priority
);