[netcore] Mark InitializeCurrentThread NoInlining (#18493)
[mono-project.git] / netcore / System.Private.CoreLib / src / System / Threading / Thread.Mono.cs
blob202225aa64f2a9969529373be8052a9fe40e0d5b
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)]
15 partial class Thread
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
19 int lock_thread_id;
20 // stores a thread handle
21 IntPtr handle;
22 IntPtr native_handle; // used only on Win32
23 /* accessed only from unmanaged code */
24 private IntPtr name;
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;
51 private int small_id;
52 private IntPtr manage_callback;
53 private IntPtr flags;
54 private IntPtr thread_pinning_ref;
55 private IntPtr abort_protected_block_count;
56 private int priority;
57 private IntPtr owned_mutex;
58 private IntPtr suspended_event;
59 private int self_suspended;
60 private IntPtr thread_state;
62 private Thread self;
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! */
70 private IntPtr last;
71 #endregion
72 #pragma warning restore 169, 414, 649
74 string _name;
75 Delegate m_start;
76 object m_start_arg;
77 CultureInfo culture, ui_culture;
78 internal ExecutionContext _executionContext;
79 internal SynchronizationContext _synchronizationContext;
81 Thread ()
83 InitInternal (this);
86 ~Thread ()
88 FreeInternal ();
91 internal static ulong CurrentOSThreadId {
92 get {
93 return GetCurrentOSThreadId ();
97 public bool IsAlive {
98 get {
99 var state = GetState (this);
100 return (state & (ThreadState.Unstarted | ThreadState.Stopped | ThreadState.Aborted)) == 0;
104 public bool IsBackground {
105 get {
106 var state = ValidateThreadState ();
107 return (state & ThreadState.Background) != 0;
109 set {
110 ValidateThreadState ();
111 if (value) {
112 SetState (this, ThreadState.Background);
113 } else {
114 ClrState (this, ThreadState.Background);
119 public bool IsThreadPoolThread {
120 get {
121 ValidateThreadState ();
122 return threadpool_thread;
124 internal set {
125 threadpool_thread = value;
129 public int ManagedThreadId => managed_id;
131 internal static int OptimalMaxSpinWaitsPerSpinIteration {
132 get {
133 // Default from coreclr (src/utilcode/yieldprocessornormalized.cpp)
134 return 7;
138 public ThreadPriority Priority {
139 get {
140 ValidateThreadState ();
141 return (ThreadPriority) priority;
143 set {
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 ()
163 // no-op
166 [MethodImplAttribute(MethodImplOptions.InternalCall)]
167 extern static int GetCurrentProcessorNumber ();
169 public static int GetCurrentProcessorId ()
171 int id = GetCurrentProcessorNumber ();
173 if (id < 0)
174 id = Environment.CurrentManagedThreadId;
176 return id;
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 ()
193 if (_name != null)
194 Name = null;
196 if ((state & ThreadState.Background) == 0)
197 IsBackground = true;
199 if ((ThreadPriority) priority != ThreadPriority.Normal)
200 Priority = ThreadPriority.Normal;
203 void SetCultureOnUnstartedThreadNoCheck (CultureInfo value, bool uiCulture)
205 if (uiCulture)
206 ui_culture = value;
207 else
208 culture = value;
211 void SetStartHelper (Delegate start, int maxStackSize)
213 m_start = start;
214 stack_size = maxStackSize;
217 public static void SpinWait (int iterations)
219 if (iterations < 0)
220 return;
222 while (iterations-- > 0)
223 SpinWait_nop ();
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);
236 public void Start ()
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 ()
253 if (culture != null)
254 CurrentCulture = culture;
255 if (ui_culture != null)
256 CurrentUICulture = ui_culture;
257 if (m_start is ThreadStart del) {
258 m_start = null;
259 del ();
260 } else {
261 var pdel = (ParameterizedThreadStart) m_start;
262 var arg = m_start_arg;
263 m_start = null;
264 m_start_arg = null;
265 pdel (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.");
287 return state;
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);
303 return 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);
336 [Intrinsic]
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);