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.Runtime.ConstrainedExecution;
44 namespace System.Threading {
45 [StructLayout (LayoutKind.Sequential)]
46 sealed class InternalThread : CriticalFinalizerObject {
47 #pragma warning disable 169, 414, 649
48 #region Sync with metadata/object-internals.h
50 // stores a thread handle
51 internal IntPtr system_thread_handle;
53 /* Note this is an opaque object (an array), not a CultureInfo */
54 private object cached_culture_info;
55 /* accessed only from unmanaged code */
58 private ThreadState state;
59 private object abort_exc;
60 private int abort_state_handle;
61 /* thread_id is only accessed from unmanaged code */
62 internal Int64 thread_id;
64 /* start_notify is used by the runtime to signal that Start()
67 private IntPtr start_notify;
68 private IntPtr stack_ptr;
69 private UIntPtr static_data; /* GC-tracked */
70 private IntPtr runtime_thread_info;
71 /* current System.Runtime.Remoting.Contexts.Context instance
72 keep as an object to avoid triggering its class constructor when not needed */
73 private object current_appcontext;
74 private object pending_exception;
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;
93 private IntPtr async_invoke_method;
95 * These fields are used to avoid having to increment corlib versions
96 * when a new field is added to the unmanaged MonoThread structure.
98 private IntPtr unused1;
99 private IntPtr unused2;
101 #pragma warning restore 169, 414, 649
103 // Closes the system thread handle
104 [MethodImplAttribute(MethodImplOptions.InternalCall)]
105 private extern void Thread_free_internal(IntPtr handle);
107 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
109 Thread_free_internal(system_thread_handle);
113 [StructLayout (LayoutKind.Sequential)]
114 public sealed partial class Thread {
115 #pragma warning disable 414
116 #region Sync with metadata/object-internals.h
117 private InternalThread internal_thread;
118 object m_ThreadStartArg;
120 #pragma warning restore 414
122 IPrincipal principal;
123 int principal_version;
124 bool current_culture_set;
125 bool current_ui_culture_set;
126 CultureInfo current_culture;
127 CultureInfo current_ui_culture;
129 // the name of current_thread is
130 // important because they are used by the runtime.
133 static Thread current_thread;
135 static internal CultureInfo default_culture;
136 static internal CultureInfo default_ui_culture;
138 // can be both a ThreadStart and a ParameterizedThreadStart
139 private MulticastDelegate m_Delegate;
141 private ExecutionContext m_ExecutionContext; // this call context follows the logical thread
143 private bool m_ExecutionContextBelongsToOuterScope;
145 [MethodImplAttribute(MethodImplOptions.InternalCall)]
146 private extern void ConstructInternalThread ();
148 private InternalThread Internal {
150 if (internal_thread == null)
151 ConstructInternalThread ();
152 return internal_thread;
156 public static Context CurrentContext {
157 [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
159 return(AppDomain.InternalGetContext ());
164 * These two methods return an array in the target
165 * domain with the same content as the argument. If
166 * the argument is already in the target domain, then
167 * the argument is returned, otherwise a copy.
169 [MethodImplAttribute(MethodImplOptions.InternalCall)]
170 private extern static byte[] ByteArrayToRootDomain (byte[] arr);
172 [MethodImplAttribute(MethodImplOptions.InternalCall)]
173 private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
175 static void DeserializePrincipal (Thread th)
177 MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
178 int type = ms.ReadByte ();
180 BinaryFormatter bf = new BinaryFormatter ();
181 th.principal = (IPrincipal) bf.Deserialize (ms);
182 th.principal_version = th.Internal._serialized_principal_version;
183 } else if (type == 1) {
184 BinaryReader reader = new BinaryReader (ms);
185 string name = reader.ReadString ();
186 string auth_type = reader.ReadString ();
187 int n_roles = reader.ReadInt32 ();
188 string [] roles = null;
190 roles = new string [n_roles];
191 for (int i = 0; i < n_roles; i++)
192 roles [i] = reader.ReadString ();
194 th.principal = new GenericPrincipal (new GenericIdentity (name, auth_type), roles);
195 } else if (type == 2 || type == 3) {
196 string [] roles = type == 2 ? null : new string [0];
197 th.principal = new GenericPrincipal (new GenericIdentity ("", ""), roles);
201 static void SerializePrincipal (Thread th, IPrincipal value)
203 MemoryStream ms = new MemoryStream ();
205 if (value.GetType () == typeof (GenericPrincipal)) {
206 GenericPrincipal gp = (GenericPrincipal) value;
207 if (gp.Identity != null && gp.Identity.GetType () == typeof (GenericIdentity)) {
208 GenericIdentity id = (GenericIdentity) gp.Identity;
209 if (id.Name == "" && id.AuthenticationType == "") {
210 if (gp.Roles == null) {
213 } else if (gp.Roles.Length == 0) {
219 BinaryWriter br = new BinaryWriter (ms);
220 br.Write (gp.Identity.Name);
221 br.Write (gp.Identity.AuthenticationType);
222 string [] roles = gp.Roles;
224 br.Write ((int) (-1));
226 br.Write (roles.Length);
227 foreach (string s in roles) {
238 BinaryFormatter bf = new BinaryFormatter ();
240 bf.Serialize (ms, value);
243 th.Internal._serialized_principal = ByteArrayToRootDomain (ms.ToArray ());
246 public static IPrincipal CurrentPrincipal {
248 Thread th = CurrentThread;
250 if (th.principal_version != th.Internal._serialized_principal_version)
253 if (th.principal != null)
256 if (th.Internal._serialized_principal != null) {
258 DeserializePrincipal (th);
263 th.principal = GetDomain ().DefaultPrincipal;
264 th.principal_version = th.Internal._serialized_principal_version;
267 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
269 Thread th = CurrentThread;
271 if (value != GetDomain ().DefaultPrincipal) {
272 ++th.Internal._serialized_principal_version;
274 SerializePrincipal (th, value);
275 } catch (Exception) {
276 th.Internal._serialized_principal = null;
278 th.principal_version = th.Internal._serialized_principal_version;
280 th.Internal._serialized_principal = null;
283 th.principal = value;
287 // Looks up the object associated with the current thread
288 // this is called by the JIT directly, too
289 [MethodImplAttribute(MethodImplOptions.InternalCall)]
290 private extern static InternalThread CurrentInternalThread_internal();
292 public static Thread CurrentThread {
293 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
295 if (current_thread == null)
296 current_thread = new Thread (CurrentInternalThread_internal ());
297 return current_thread;
301 internal static int CurrentThreadId {
303 return (int)(CurrentThread.internal_thread.thread_id);
307 public static AppDomain GetDomain() {
308 return AppDomain.CurrentDomain;
311 [MethodImplAttribute(MethodImplOptions.InternalCall)]
312 public extern static int GetDomainID();
314 // Returns the system thread handle
315 [MethodImplAttribute(MethodImplOptions.InternalCall)]
316 private extern IntPtr Thread_internal (MulticastDelegate start);
318 private Thread (InternalThread it) {
319 internal_thread = it;
322 // part of ".NETPortable,Version=v4.0,Profile=Profile3" i.e. FX4 and SL4
323 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
328 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
329 public ApartmentState ApartmentState {
331 if ((ThreadState & ThreadState.Stopped) != 0)
332 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
334 return (ApartmentState)Internal.apartment_state;
338 TrySetApartmentState (value);
342 //[MethodImplAttribute (MethodImplOptions.InternalCall)]
343 //private static extern int current_lcid ();
345 public CultureInfo CurrentCulture {
347 CultureInfo culture = current_culture;
348 if (current_culture_set && culture != null)
351 if (default_culture != null)
352 return default_culture;
354 current_culture = culture = CultureInfo.ConstructCurrentCulture ();
358 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
361 throw new ArgumentNullException ("value");
363 value.CheckNeutral ();
364 current_culture = value;
365 current_culture_set = true;
369 public CultureInfo CurrentUICulture {
371 CultureInfo culture = current_ui_culture;
372 if (current_ui_culture_set && culture != null)
375 if (default_ui_culture != null)
376 return default_ui_culture;
378 current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
384 throw new ArgumentNullException ("value");
385 current_ui_culture = value;
386 current_ui_culture_set = true;
390 public bool IsThreadPoolThread {
392 return IsThreadPoolThreadInternal;
396 internal bool IsThreadPoolThreadInternal {
398 return Internal.threadpool_thread;
401 Internal.threadpool_thread = value;
405 public bool IsAlive {
407 ThreadState curstate = GetState (Internal);
409 if((curstate & ThreadState.Aborted) != 0 ||
410 (curstate & ThreadState.Stopped) != 0 ||
411 (curstate & ThreadState.Unstarted) != 0) {
419 public bool IsBackground {
421 ThreadState thread_state = GetState (Internal);
422 if ((thread_state & ThreadState.Stopped) != 0)
423 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
425 return (thread_state & ThreadState.Background) != 0;
430 SetState (Internal, ThreadState.Background);
432 ClrState (Internal, ThreadState.Background);
437 [MethodImplAttribute(MethodImplOptions.InternalCall)]
438 private extern static string GetName_internal (InternalThread thread);
440 [MethodImplAttribute(MethodImplOptions.InternalCall)]
441 private extern static void SetName_internal (InternalThread thread, String name);
444 * The thread name must be shared by appdomains, so it is stored in
450 return GetName_internal (Internal);
454 SetName_internal (Internal, value);
458 public ThreadState ThreadState {
460 return GetState (Internal);
464 [MethodImplAttribute(MethodImplOptions.InternalCall)]
465 private extern static void Abort_internal (InternalThread thread, object stateInfo);
467 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
470 Abort_internal (Internal, null);
473 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
474 public void Abort (object stateInfo)
476 Abort_internal (Internal, stateInfo);
479 [MethodImplAttribute(MethodImplOptions.InternalCall)]
480 extern object GetAbortExceptionState ();
482 internal object AbortReason {
484 return GetAbortExceptionState ();
488 void ClearAbortReason ()
492 [MethodImplAttribute (MethodImplOptions.InternalCall)]
493 private extern static void SpinWait_nop ();
496 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
497 public static void SpinWait (int iterations)
501 while (iterations-- > 0)
507 void StartInternal (IPrincipal principal, ref StackCrawlMark stackMark)
509 #if FEATURE_ROLE_BASED_SECURITY
510 Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
513 // Thread_internal creates and starts the new thread,
514 if (Thread_internal(m_Delegate) == IntPtr.Zero)
515 throw new SystemException ("Thread creation failed.");
517 m_ThreadStartArg = null;
520 [MethodImplAttribute (MethodImplOptions.InternalCall)]
521 extern private static void SetState (InternalThread thread, ThreadState set);
523 [MethodImplAttribute (MethodImplOptions.InternalCall)]
524 extern private static void ClrState (InternalThread thread, ThreadState clr);
526 [MethodImplAttribute (MethodImplOptions.InternalCall)]
527 extern private static ThreadState GetState (InternalThread thread);
529 [MethodImplAttribute (MethodImplOptions.InternalCall)]
530 extern public static byte VolatileRead (ref byte address);
532 [MethodImplAttribute (MethodImplOptions.InternalCall)]
533 extern public static double VolatileRead (ref double address);
535 [MethodImplAttribute (MethodImplOptions.InternalCall)]
536 extern public static short VolatileRead (ref short address);
538 [MethodImplAttribute (MethodImplOptions.InternalCall)]
539 extern public static int VolatileRead (ref int address);
541 [MethodImplAttribute (MethodImplOptions.InternalCall)]
542 extern public static long VolatileRead (ref long address);
544 [MethodImplAttribute (MethodImplOptions.InternalCall)]
545 extern public static IntPtr VolatileRead (ref IntPtr address);
547 [MethodImplAttribute (MethodImplOptions.InternalCall)]
548 extern public static object VolatileRead (ref object address);
550 [CLSCompliant(false)]
551 [MethodImplAttribute (MethodImplOptions.InternalCall)]
552 extern public static sbyte VolatileRead (ref sbyte address);
554 [MethodImplAttribute (MethodImplOptions.InternalCall)]
555 extern public static float VolatileRead (ref float address);
557 [CLSCompliant (false)]
558 [MethodImplAttribute (MethodImplOptions.InternalCall)]
559 extern public static ushort VolatileRead (ref ushort address);
561 [CLSCompliant (false)]
562 [MethodImplAttribute (MethodImplOptions.InternalCall)]
563 extern public static uint VolatileRead (ref uint address);
565 [CLSCompliant (false)]
566 [MethodImplAttribute (MethodImplOptions.InternalCall)]
567 extern public static ulong VolatileRead (ref ulong address);
569 [CLSCompliant (false)]
570 [MethodImplAttribute (MethodImplOptions.InternalCall)]
571 extern public static UIntPtr VolatileRead (ref UIntPtr address);
573 [MethodImplAttribute (MethodImplOptions.InternalCall)]
574 extern public static void VolatileWrite (ref byte address, byte value);
576 [MethodImplAttribute (MethodImplOptions.InternalCall)]
577 extern public static void VolatileWrite (ref double address, double value);
579 [MethodImplAttribute (MethodImplOptions.InternalCall)]
580 extern public static void VolatileWrite (ref short address, short value);
582 [MethodImplAttribute (MethodImplOptions.InternalCall)]
583 extern public static void VolatileWrite (ref int address, int value);
585 [MethodImplAttribute (MethodImplOptions.InternalCall)]
586 extern public static void VolatileWrite (ref long address, long value);
588 [MethodImplAttribute (MethodImplOptions.InternalCall)]
589 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
591 [MethodImplAttribute (MethodImplOptions.InternalCall)]
592 extern public static void VolatileWrite (ref object address, object value);
594 [CLSCompliant(false)]
595 [MethodImplAttribute (MethodImplOptions.InternalCall)]
596 extern public static void VolatileWrite (ref sbyte address, sbyte value);
598 [MethodImplAttribute (MethodImplOptions.InternalCall)]
599 extern public static void VolatileWrite (ref float address, float value);
601 [CLSCompliant (false)]
602 [MethodImplAttribute (MethodImplOptions.InternalCall)]
603 extern public static void VolatileWrite (ref ushort address, ushort value);
605 [CLSCompliant (false)]
606 [MethodImplAttribute (MethodImplOptions.InternalCall)]
607 extern public static void VolatileWrite (ref uint address, uint value);
609 [CLSCompliant (false)]
610 [MethodImplAttribute (MethodImplOptions.InternalCall)]
611 extern public static void VolatileWrite (ref ulong address, ulong value);
613 [CLSCompliant (false)]
614 [MethodImplAttribute (MethodImplOptions.InternalCall)]
615 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
617 [MethodImplAttribute (MethodImplOptions.InternalCall)]
618 extern static int SystemMaxStackStize ();
620 static int GetProcessDefaultStackSize (int maxStackSize)
622 if (maxStackSize == 0)
625 if (maxStackSize < 131072) // make sure stack is at least 128k big
628 int page_size = Environment.GetPageSize ();
630 if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
631 maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
633 /* Respect the max stack size imposed by the system*/
634 return Math.Min (maxStackSize, SystemMaxStackStize ());
637 void SetStart (MulticastDelegate start, int maxStackSize)
640 Internal.stack_size = maxStackSize;
643 public int ManagedThreadId {
644 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
646 return Internal.managed_id;
650 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
651 public static void BeginCriticalRegion ()
653 CurrentThread.Internal.critical_region_level++;
656 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
657 public static void EndCriticalRegion ()
659 CurrentThread.Internal.critical_region_level--;
662 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
663 public static void BeginThreadAffinity ()
665 // Managed and native threads are currently bound together.
668 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
669 public static void EndThreadAffinity ()
671 // Managed and native threads are currently bound together.
674 public ApartmentState GetApartmentState ()
676 return (ApartmentState)Internal.apartment_state;
679 public void SetApartmentState (ApartmentState state)
681 if (!TrySetApartmentState (state))
682 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
685 public bool TrySetApartmentState (ApartmentState state)
687 if ((ThreadState & ThreadState.Unstarted) == 0)
688 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
690 if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown &&
691 (ApartmentState)Internal.apartment_state != state)
694 Internal.apartment_state = (byte)state;
700 public override int GetHashCode ()
702 return ManagedThreadId;
705 internal CultureInfo GetCurrentUICultureNoAppX ()
707 return CultureInfo.CurrentUICulture;