2 // System.Threading.Thread.cs
5 // Dick Porter (dick@ximian.com)
7 // (C) Ximian, Inc. http://www.ximian.com
8 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Runtime.Remoting.Contexts;
31 using System.Runtime.Serialization;
32 using System.Runtime.Serialization.Formatters.Binary;
33 using System.Security.Permissions;
34 using System.Security.Principal;
35 using System.Globalization;
36 using System.Runtime.CompilerServices;
37 using System.Runtime.InteropServices;
39 using System.Collections.Generic;
40 using System.Reflection;
41 using System.Security;
42 using System.Diagnostics;
43 using System.Runtime.ConstrainedExecution;
45 namespace System.Threading {
46 [StructLayout (LayoutKind.Sequential)]
47 sealed class InternalThread : CriticalFinalizerObject {
48 #pragma warning disable 169, 414, 649
49 #region Sync with metadata/object-internals.h
51 // stores a thread handle
52 internal IntPtr system_thread_handle;
54 /* Note this is an opaque object (an array), not a CultureInfo */
55 private object cached_culture_info;
56 /* accessed only from unmanaged code */
59 private ThreadState state;
60 private object abort_exc;
61 private int abort_state_handle;
62 /* thread_id is only accessed from unmanaged code */
63 internal Int64 thread_id;
65 /* start_notify is used by the runtime to signal that Start()
68 private IntPtr start_notify;
69 private IntPtr stack_ptr;
70 private UIntPtr static_data; /* GC-tracked */
71 private IntPtr runtime_thread_info;
72 /* current System.Runtime.Remoting.Contexts.Context instance
73 keep as an object to avoid triggering its class constructor when not needed */
74 private object current_appcontext;
75 private object root_domain_thread;
76 internal byte[] _serialized_principal;
77 internal int _serialized_principal_version;
78 private IntPtr appdomain_refs;
79 private int interruption_requested;
80 private IntPtr synch_cs;
81 internal bool threadpool_thread;
82 private bool thread_interrupt_requested;
83 /* These are used from managed code */
84 internal int stack_size;
85 internal byte apartment_state;
86 internal volatile int critical_region_level;
87 internal int managed_id;
89 private IntPtr manage_callback;
90 private IntPtr interrupt_on_stop;
92 private IntPtr thread_pinning_ref;
94 * These fields are used to avoid having to increment corlib versions
95 * when a new field is added to the unmanaged MonoThread structure.
97 private IntPtr unused1;
98 private IntPtr unused2;
100 #pragma warning restore 169, 414, 649
102 // Closes the system thread handle
103 [MethodImplAttribute(MethodImplOptions.InternalCall)]
104 private extern void Thread_free_internal(IntPtr handle);
106 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
108 Thread_free_internal(system_thread_handle);
112 [StructLayout (LayoutKind.Sequential)]
113 public sealed partial class Thread {
114 #pragma warning disable 414
115 #region Sync with metadata/object-internals.h
116 private InternalThread internal_thread;
117 object m_ThreadStartArg;
118 object pending_exception;
119 int priority = (int) ThreadPriority.Normal;
121 #pragma warning restore 414
123 IPrincipal principal;
124 int principal_version;
125 bool current_culture_set;
126 bool current_ui_culture_set;
127 CultureInfo current_culture;
128 CultureInfo current_ui_culture;
130 // the name of current_thread is
131 // important because they are used by the runtime.
134 static Thread current_thread;
136 static internal CultureInfo default_culture;
137 static internal CultureInfo default_ui_culture;
139 // can be both a ThreadStart and a ParameterizedThreadStart
140 private MulticastDelegate m_Delegate;
142 private ExecutionContext m_ExecutionContext; // this call context follows the logical thread
144 private bool m_ExecutionContextBelongsToOuterScope;
146 [MethodImplAttribute(MethodImplOptions.InternalCall)]
147 private extern void ConstructInternalThread ();
149 private InternalThread Internal {
151 if (internal_thread == null)
152 ConstructInternalThread ();
153 return internal_thread;
157 public static Context CurrentContext {
158 [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
160 return(AppDomain.InternalGetContext ());
165 * These two methods return an array in the target
166 * domain with the same content as the argument. If
167 * the argument is already in the target domain, then
168 * the argument is returned, otherwise a copy.
170 [MethodImplAttribute(MethodImplOptions.InternalCall)]
171 private extern static byte[] ByteArrayToRootDomain (byte[] arr);
173 [MethodImplAttribute(MethodImplOptions.InternalCall)]
174 private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
176 static void DeserializePrincipal (Thread th)
178 MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
179 int type = ms.ReadByte ();
181 BinaryFormatter bf = new BinaryFormatter ();
182 th.principal = (IPrincipal) bf.Deserialize (ms);
183 th.principal_version = th.Internal._serialized_principal_version;
184 } else if (type == 1) {
185 BinaryReader reader = new BinaryReader (ms);
186 string name = reader.ReadString ();
187 string auth_type = reader.ReadString ();
188 int n_roles = reader.ReadInt32 ();
189 string [] roles = null;
191 roles = new string [n_roles];
192 for (int i = 0; i < n_roles; i++)
193 roles [i] = reader.ReadString ();
195 th.principal = new GenericPrincipal (new GenericIdentity (name, auth_type), roles);
196 } else if (type == 2 || type == 3) {
197 string [] roles = type == 2 ? null : new string [0];
198 th.principal = new GenericPrincipal (new GenericIdentity ("", ""), roles);
202 static void SerializePrincipal (Thread th, IPrincipal value)
204 MemoryStream ms = new MemoryStream ();
206 if (value.GetType () == typeof (GenericPrincipal)) {
207 GenericPrincipal gp = (GenericPrincipal) value;
208 if (gp.Identity != null && gp.Identity.GetType () == typeof (GenericIdentity)) {
209 GenericIdentity id = (GenericIdentity) gp.Identity;
210 if (id.Name == "" && id.AuthenticationType == "") {
211 if (gp.Roles == null) {
214 } else if (gp.Roles.Length == 0) {
220 BinaryWriter br = new BinaryWriter (ms);
221 br.Write (gp.Identity.Name);
222 br.Write (gp.Identity.AuthenticationType);
223 string [] roles = gp.Roles;
225 br.Write ((int) (-1));
227 br.Write (roles.Length);
228 foreach (string s in roles) {
239 BinaryFormatter bf = new BinaryFormatter ();
241 bf.Serialize (ms, value);
244 th.Internal._serialized_principal = ByteArrayToRootDomain (ms.ToArray ());
247 public static IPrincipal CurrentPrincipal {
249 Thread th = CurrentThread;
251 if (th.principal_version != th.Internal._serialized_principal_version)
254 if (th.principal != null)
257 if (th.Internal._serialized_principal != null) {
259 DeserializePrincipal (th);
264 th.principal = GetDomain ().DefaultPrincipal;
265 th.principal_version = th.Internal._serialized_principal_version;
268 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
270 Thread th = CurrentThread;
272 if (value != GetDomain ().DefaultPrincipal) {
273 ++th.Internal._serialized_principal_version;
275 SerializePrincipal (th, value);
276 } catch (Exception) {
277 th.Internal._serialized_principal = null;
279 th.principal_version = th.Internal._serialized_principal_version;
281 th.Internal._serialized_principal = null;
284 th.principal = value;
288 // Looks up the object associated with the current thread
289 // this is called by the JIT directly, too
290 [MethodImplAttribute(MethodImplOptions.InternalCall)]
291 private extern static InternalThread CurrentInternalThread_internal();
293 public static Thread CurrentThread {
294 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
296 if (current_thread == null)
297 current_thread = new Thread (CurrentInternalThread_internal ());
298 return current_thread;
302 internal static int CurrentThreadId {
304 return (int)(CurrentThread.internal_thread.thread_id);
308 public static AppDomain GetDomain() {
309 return AppDomain.CurrentDomain;
312 [MethodImplAttribute(MethodImplOptions.InternalCall)]
313 public extern static int GetDomainID();
315 // Returns the system thread handle
316 [MethodImplAttribute(MethodImplOptions.InternalCall)]
317 private extern IntPtr Thread_internal (MulticastDelegate start);
319 private Thread (InternalThread it) {
320 internal_thread = it;
323 // part of ".NETPortable,Version=v4.0,Profile=Profile3" i.e. FX4 and SL4
324 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
329 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
330 public ApartmentState ApartmentState {
332 if ((ThreadState & ThreadState.Stopped) != 0)
333 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
335 return (ApartmentState)Internal.apartment_state;
339 TrySetApartmentState (value);
343 //[MethodImplAttribute (MethodImplOptions.InternalCall)]
344 //private static extern int current_lcid ();
346 public CultureInfo CurrentCulture {
348 CultureInfo culture = current_culture;
349 if (current_culture_set && culture != null)
352 if (default_culture != null)
353 return default_culture;
355 current_culture = culture = CultureInfo.ConstructCurrentCulture ();
359 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
362 throw new ArgumentNullException ("value");
364 value.CheckNeutral ();
365 current_culture = value;
366 current_culture_set = true;
370 public CultureInfo CurrentUICulture {
372 CultureInfo culture = current_ui_culture;
373 if (current_ui_culture_set && culture != null)
376 if (default_ui_culture != null)
377 return default_ui_culture;
379 current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
385 throw new ArgumentNullException ("value");
386 current_ui_culture = value;
387 current_ui_culture_set = true;
391 public bool IsThreadPoolThread {
393 return IsThreadPoolThreadInternal;
397 internal bool IsThreadPoolThreadInternal {
399 return Internal.threadpool_thread;
402 Internal.threadpool_thread = value;
406 public bool IsAlive {
408 ThreadState curstate = GetState (Internal);
410 if((curstate & ThreadState.Aborted) != 0 ||
411 (curstate & ThreadState.Stopped) != 0 ||
412 (curstate & ThreadState.Unstarted) != 0) {
420 public bool IsBackground {
422 ThreadState thread_state = GetState (Internal);
423 if ((thread_state & ThreadState.Stopped) != 0)
424 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
426 return (thread_state & ThreadState.Background) != 0;
431 SetState (Internal, ThreadState.Background);
433 ClrState (Internal, ThreadState.Background);
438 [MethodImplAttribute(MethodImplOptions.InternalCall)]
439 private extern static string GetName_internal (InternalThread thread);
441 [MethodImplAttribute(MethodImplOptions.InternalCall)]
442 private extern static void SetName_internal (InternalThread thread, String name);
445 * The thread name must be shared by appdomains, so it is stored in
451 return GetName_internal (Internal);
455 SetName_internal (Internal, value);
459 public ThreadState ThreadState {
461 return GetState (Internal);
465 #if MONO_FEATURE_THREAD_ABORT
466 [MethodImplAttribute(MethodImplOptions.InternalCall)]
467 private extern static void Abort_internal (InternalThread thread, object stateInfo);
469 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
472 Abort_internal (Internal, null);
475 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
476 public void Abort (object stateInfo)
478 Abort_internal (Internal, stateInfo);
481 [MethodImplAttribute(MethodImplOptions.InternalCall)]
482 extern object GetAbortExceptionState ();
484 internal object AbortReason {
486 return GetAbortExceptionState ();
490 void ClearAbortReason ()
494 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
497 throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
500 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
501 public void Abort (object stateInfo)
503 throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
506 [Obsolete ("Thread.ResetAbort is not supported on the current platform.", true)]
507 public static void ResetAbort ()
509 throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
511 #endif // MONO_FEATURE_THREAD_ABORT
513 [MethodImplAttribute (MethodImplOptions.InternalCall)]
514 private extern static void SpinWait_nop ();
517 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
518 public static void SpinWait (int iterations)
522 while (iterations-- > 0)
528 void StartInternal (IPrincipal principal, ref StackCrawlMark stackMark)
530 #if FEATURE_ROLE_BASED_SECURITY
531 Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
534 // Thread_internal creates and starts the new thread,
535 if (Thread_internal(m_Delegate) == IntPtr.Zero)
536 throw new SystemException ("Thread creation failed.");
538 m_ThreadStartArg = null;
541 [MethodImplAttribute (MethodImplOptions.InternalCall)]
542 extern private static void SetState (InternalThread thread, ThreadState set);
544 [MethodImplAttribute (MethodImplOptions.InternalCall)]
545 extern private static void ClrState (InternalThread thread, ThreadState clr);
547 [MethodImplAttribute (MethodImplOptions.InternalCall)]
548 extern private static ThreadState GetState (InternalThread thread);
550 [MethodImplAttribute (MethodImplOptions.InternalCall)]
551 extern public static byte VolatileRead (ref byte address);
553 [MethodImplAttribute (MethodImplOptions.InternalCall)]
554 extern public static double VolatileRead (ref double address);
556 [MethodImplAttribute (MethodImplOptions.InternalCall)]
557 extern public static short VolatileRead (ref short address);
559 [MethodImplAttribute (MethodImplOptions.InternalCall)]
560 extern public static int VolatileRead (ref int address);
562 [MethodImplAttribute (MethodImplOptions.InternalCall)]
563 extern public static long VolatileRead (ref long address);
565 [MethodImplAttribute (MethodImplOptions.InternalCall)]
566 extern public static IntPtr VolatileRead (ref IntPtr address);
568 [MethodImplAttribute (MethodImplOptions.InternalCall)]
569 extern public static object VolatileRead (ref object address);
571 [CLSCompliant(false)]
572 [MethodImplAttribute (MethodImplOptions.InternalCall)]
573 extern public static sbyte VolatileRead (ref sbyte address);
575 [MethodImplAttribute (MethodImplOptions.InternalCall)]
576 extern public static float VolatileRead (ref float address);
578 [CLSCompliant (false)]
579 [MethodImplAttribute (MethodImplOptions.InternalCall)]
580 extern public static ushort VolatileRead (ref ushort address);
582 [CLSCompliant (false)]
583 [MethodImplAttribute (MethodImplOptions.InternalCall)]
584 extern public static uint VolatileRead (ref uint address);
586 [CLSCompliant (false)]
587 [MethodImplAttribute (MethodImplOptions.InternalCall)]
588 extern public static ulong VolatileRead (ref ulong address);
590 [CLSCompliant (false)]
591 [MethodImplAttribute (MethodImplOptions.InternalCall)]
592 extern public static UIntPtr VolatileRead (ref UIntPtr address);
594 [MethodImplAttribute (MethodImplOptions.InternalCall)]
595 extern public static void VolatileWrite (ref byte address, byte value);
597 [MethodImplAttribute (MethodImplOptions.InternalCall)]
598 extern public static void VolatileWrite (ref double address, double value);
600 [MethodImplAttribute (MethodImplOptions.InternalCall)]
601 extern public static void VolatileWrite (ref short address, short value);
603 [MethodImplAttribute (MethodImplOptions.InternalCall)]
604 extern public static void VolatileWrite (ref int address, int value);
606 [MethodImplAttribute (MethodImplOptions.InternalCall)]
607 extern public static void VolatileWrite (ref long address, long value);
609 [MethodImplAttribute (MethodImplOptions.InternalCall)]
610 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
612 [MethodImplAttribute (MethodImplOptions.InternalCall)]
613 extern public static void VolatileWrite (ref object address, object value);
615 [CLSCompliant(false)]
616 [MethodImplAttribute (MethodImplOptions.InternalCall)]
617 extern public static void VolatileWrite (ref sbyte address, sbyte value);
619 [MethodImplAttribute (MethodImplOptions.InternalCall)]
620 extern public static void VolatileWrite (ref float address, float value);
622 [CLSCompliant (false)]
623 [MethodImplAttribute (MethodImplOptions.InternalCall)]
624 extern public static void VolatileWrite (ref ushort address, ushort value);
626 [CLSCompliant (false)]
627 [MethodImplAttribute (MethodImplOptions.InternalCall)]
628 extern public static void VolatileWrite (ref uint address, uint value);
630 [CLSCompliant (false)]
631 [MethodImplAttribute (MethodImplOptions.InternalCall)]
632 extern public static void VolatileWrite (ref ulong address, ulong value);
634 [CLSCompliant (false)]
635 [MethodImplAttribute (MethodImplOptions.InternalCall)]
636 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
638 [MethodImplAttribute (MethodImplOptions.InternalCall)]
639 extern static int SystemMaxStackStize ();
641 static int GetProcessDefaultStackSize (int maxStackSize)
643 if (maxStackSize == 0)
646 if (maxStackSize < 131072) // make sure stack is at least 128k big
649 int page_size = Environment.GetPageSize ();
651 if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
652 maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
654 /* Respect the max stack size imposed by the system*/
655 return Math.Min (maxStackSize, SystemMaxStackStize ());
658 void SetStart (MulticastDelegate start, int maxStackSize)
661 Internal.stack_size = maxStackSize;
664 public int ManagedThreadId {
665 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
667 return Internal.managed_id;
671 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
672 public static void BeginCriticalRegion ()
674 CurrentThread.Internal.critical_region_level++;
677 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
678 public static void EndCriticalRegion ()
680 CurrentThread.Internal.critical_region_level--;
683 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
684 public static void BeginThreadAffinity ()
686 // Managed and native threads are currently bound together.
689 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
690 public static void EndThreadAffinity ()
692 // Managed and native threads are currently bound together.
695 public ApartmentState GetApartmentState ()
697 return (ApartmentState)Internal.apartment_state;
700 public void SetApartmentState (ApartmentState state)
702 if (!TrySetApartmentState (state))
703 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
706 public bool TrySetApartmentState (ApartmentState state)
708 if ((ThreadState & ThreadState.Unstarted) == 0)
709 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
711 if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown &&
712 (ApartmentState)Internal.apartment_state != state)
715 Internal.apartment_state = (byte)state;
721 public override int GetHashCode ()
723 return ManagedThreadId;
726 internal CultureInfo GetCurrentUICultureNoAppX ()
728 return CultureInfo.CurrentUICulture;
731 [MethodImplAttribute(MethodImplOptions.InternalCall)]
732 internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
734 // This is a mono extension to gather the stack traces for all running threads
735 internal static Dictionary<Thread, StackTrace> Mono_GetStackTraces () {
737 object[] stack_frames;
739 GetStackTraces (out threads, out stack_frames);
741 var res = new Dictionary<Thread, StackTrace> ();
742 for (int i = 0; i < threads.Length; ++i)
743 res [threads [i]] = new StackTrace ((StackFrame[])stack_frames [i]);
747 #if !MONO_FEATURE_THREAD_SUSPEND_RESUME
748 [Obsolete ("Thread.Suspend is not supported on the current platform.", true)]
749 public void Suspend ()
751 throw new PlatformNotSupportedException ("Thread.Suspend is not supported on the current platform.");
754 [Obsolete ("Thread.Resume is not supported on the current platform.", true)]
755 public void Resume ()
757 throw new PlatformNotSupportedException ("Thread.Resume is not supported on the current platform.");