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
53 IntPtr native_handle; // used only on Win32
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;
63 private IntPtr debugger_thread; // FIXME switch to bool as soon as CI testing with corlib version bump works
64 private UIntPtr static_data; /* GC-tracked */
65 private IntPtr runtime_thread_info;
66 /* current System.Runtime.Remoting.Contexts.Context instance
67 keep as an object to avoid triggering its class constructor when not needed */
68 private object current_appcontext;
69 private object root_domain_thread;
70 internal byte[] _serialized_principal;
71 internal int _serialized_principal_version;
72 private IntPtr appdomain_refs;
73 private int interruption_requested;
74 private IntPtr synch_cs;
75 internal bool threadpool_thread;
76 private bool thread_interrupt_requested;
77 /* These are used from managed code */
78 internal int stack_size;
79 internal byte apartment_state;
80 internal volatile int critical_region_level;
81 internal int managed_id;
83 private IntPtr manage_callback;
84 private IntPtr unused4;
86 private IntPtr thread_pinning_ref;
87 private IntPtr abort_protected_block_count;
88 private int priority = (int) ThreadPriority.Normal;
89 private IntPtr owned_mutex;
90 private IntPtr suspended_event;
91 private int self_suspended;
93 * These fields are used to avoid having to increment corlib versions
94 * when a new field is added to the unmanaged MonoThread structure.
96 private IntPtr unused1;
97 private IntPtr unused2;
99 /* This is used only to check that we are in sync between the representation
100 * of MonoInternalThread in native and InternalThread in managed
102 * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */
105 #pragma warning restore 169, 414, 649
107 // Closes the system thread handle
108 [MethodImplAttribute(MethodImplOptions.InternalCall)]
109 private extern void Thread_free_internal();
111 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
113 Thread_free_internal();
117 [StructLayout (LayoutKind.Sequential)]
118 public sealed partial class Thread {
119 #pragma warning disable 414
120 #region Sync with metadata/object-internals.h
121 private InternalThread internal_thread;
122 object m_ThreadStartArg;
123 object pending_exception;
125 #pragma warning restore 414
127 IPrincipal principal;
128 int principal_version;
130 // the name of current_thread is
131 // important because they are used by the runtime.
134 static Thread current_thread;
136 // can be both a ThreadStart and a ParameterizedThreadStart
137 private MulticastDelegate m_Delegate;
139 private ExecutionContext m_ExecutionContext; // this call context follows the logical thread
141 private bool m_ExecutionContextBelongsToOuterScope;
143 [MethodImplAttribute(MethodImplOptions.InternalCall)]
144 private extern void ConstructInternalThread ();
146 private InternalThread Internal {
148 if (internal_thread == null)
149 ConstructInternalThread ();
150 return internal_thread;
154 public static Context CurrentContext {
155 [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
157 return(AppDomain.InternalGetContext ());
162 * These two methods return an array in the target
163 * domain with the same content as the argument. If
164 * the argument is already in the target domain, then
165 * the argument is returned, otherwise a copy.
167 [MethodImplAttribute(MethodImplOptions.InternalCall)]
168 private extern static byte[] ByteArrayToRootDomain (byte[] arr);
170 [MethodImplAttribute(MethodImplOptions.InternalCall)]
171 private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
173 static void DeserializePrincipal (Thread th)
175 MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
176 int type = ms.ReadByte ();
178 BinaryFormatter bf = new BinaryFormatter ();
179 th.principal = (IPrincipal) bf.Deserialize (ms);
180 th.principal_version = th.Internal._serialized_principal_version;
181 } else if (type == 1) {
182 BinaryReader reader = new BinaryReader (ms);
183 string name = reader.ReadString ();
184 string auth_type = reader.ReadString ();
185 int n_roles = reader.ReadInt32 ();
186 string [] roles = null;
188 roles = new string [n_roles];
189 for (int i = 0; i < n_roles; i++)
190 roles [i] = reader.ReadString ();
192 th.principal = new GenericPrincipal (new GenericIdentity (name, auth_type), roles);
193 } else if (type == 2 || type == 3) {
194 string [] roles = type == 2 ? null : new string [0];
195 th.principal = new GenericPrincipal (new GenericIdentity ("", ""), roles);
199 static void SerializePrincipal (Thread th, IPrincipal value)
201 MemoryStream ms = new MemoryStream ();
203 if (value.GetType () == typeof (GenericPrincipal)) {
204 GenericPrincipal gp = (GenericPrincipal) value;
205 if (gp.Identity != null && gp.Identity.GetType () == typeof (GenericIdentity)) {
206 GenericIdentity id = (GenericIdentity) gp.Identity;
207 if (id.Name == "" && id.AuthenticationType == "") {
208 if (gp.Roles == null) {
211 } else if (gp.Roles.Length == 0) {
217 BinaryWriter br = new BinaryWriter (ms);
218 br.Write (gp.Identity.Name);
219 br.Write (gp.Identity.AuthenticationType);
220 string [] roles = gp.Roles;
222 br.Write ((int) (-1));
224 br.Write (roles.Length);
225 foreach (string s in roles) {
236 BinaryFormatter bf = new BinaryFormatter ();
238 bf.Serialize (ms, value);
241 th.Internal._serialized_principal = ByteArrayToRootDomain (ms.ToArray ());
244 public static IPrincipal CurrentPrincipal {
246 Thread th = CurrentThread;
248 if (th.principal_version != th.Internal._serialized_principal_version)
251 if (th.principal != null)
254 if (th.Internal._serialized_principal != null) {
256 DeserializePrincipal (th);
261 th.principal = GetDomain ().DefaultPrincipal;
262 th.principal_version = th.Internal._serialized_principal_version;
265 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
267 Thread th = CurrentThread;
269 if (value != GetDomain ().DefaultPrincipal) {
270 ++th.Internal._serialized_principal_version;
272 SerializePrincipal (th, value);
273 } catch (Exception) {
274 th.Internal._serialized_principal = null;
276 th.principal_version = th.Internal._serialized_principal_version;
278 th.Internal._serialized_principal = null;
281 th.principal = value;
285 [MethodImplAttribute(MethodImplOptions.InternalCall)]
286 private extern static Thread GetCurrentThread ();
288 public static Thread CurrentThread {
289 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
291 Thread current = current_thread;
294 // This will set the current_thread tls variable
295 return GetCurrentThread ();
299 internal static int CurrentThreadId {
301 return (int)(CurrentThread.internal_thread.thread_id);
305 public static AppDomain GetDomain() {
306 return AppDomain.CurrentDomain;
309 [MethodImplAttribute(MethodImplOptions.InternalCall)]
310 public extern static int GetDomainID();
312 // Returns the system thread handle
313 [MethodImplAttribute(MethodImplOptions.InternalCall)]
314 private extern IntPtr Thread_internal (MulticastDelegate start);
316 private Thread (InternalThread it) {
317 internal_thread = it;
320 // part of ".NETPortable,Version=v4.0,Profile=Profile3" i.e. FX4 and SL4
321 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
326 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
327 public ApartmentState ApartmentState {
329 if ((ThreadState & ThreadState.Stopped) != 0)
330 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
332 return (ApartmentState)Internal.apartment_state;
336 TrySetApartmentState (value);
340 public bool IsThreadPoolThread {
342 return IsThreadPoolThreadInternal;
346 internal bool IsThreadPoolThreadInternal {
348 return Internal.threadpool_thread;
351 Internal.threadpool_thread = value;
355 public bool IsAlive {
357 ThreadState curstate = GetState (Internal);
359 if((curstate & ThreadState.Aborted) != 0 ||
360 (curstate & ThreadState.Stopped) != 0 ||
361 (curstate & ThreadState.Unstarted) != 0) {
369 public bool IsBackground {
371 ThreadState thread_state = GetState (Internal);
372 if ((thread_state & ThreadState.Stopped) != 0)
373 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
375 return (thread_state & ThreadState.Background) != 0;
380 SetState (Internal, ThreadState.Background);
382 ClrState (Internal, ThreadState.Background);
387 [MethodImplAttribute(MethodImplOptions.InternalCall)]
388 private extern static string GetName_internal (InternalThread thread);
390 [MethodImplAttribute(MethodImplOptions.InternalCall)]
391 private extern static void SetName_internal (InternalThread thread, String name);
394 * The thread name must be shared by appdomains, so it is stored in
400 return GetName_internal (Internal);
404 SetName_internal (Internal, value);
408 public ThreadState ThreadState {
410 return GetState (Internal);
414 #if MONO_FEATURE_THREAD_ABORT
415 [MethodImplAttribute(MethodImplOptions.InternalCall)]
416 private extern static void Abort_internal (InternalThread thread, object stateInfo);
418 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
421 Abort_internal (Internal, null);
424 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
425 public void Abort (object stateInfo)
427 Abort_internal (Internal, stateInfo);
430 [MethodImplAttribute(MethodImplOptions.InternalCall)]
431 extern object GetAbortExceptionState ();
433 internal object AbortReason {
435 return GetAbortExceptionState ();
439 void ClearAbortReason ()
443 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
446 throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
449 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
450 public void Abort (object stateInfo)
452 throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
455 [Obsolete ("Thread.ResetAbort is not supported on the current platform.", true)]
456 public static void ResetAbort ()
458 throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
461 internal object AbortReason {
463 throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
466 #endif // MONO_FEATURE_THREAD_ABORT
468 [MethodImplAttribute (MethodImplOptions.InternalCall)]
469 private extern static void SpinWait_nop ();
472 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
473 public static void SpinWait (int iterations)
477 while (iterations-- > 0)
483 void StartInternal (IPrincipal principal, ref StackCrawlMark stackMark)
485 #if FEATURE_ROLE_BASED_SECURITY
486 Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
489 // Thread_internal creates and starts the new thread,
490 if (Thread_internal(m_Delegate) == IntPtr.Zero)
491 throw new SystemException ("Thread creation failed.");
493 m_ThreadStartArg = null;
496 [MethodImplAttribute (MethodImplOptions.InternalCall)]
497 extern private static void SetState (InternalThread thread, ThreadState set);
499 [MethodImplAttribute (MethodImplOptions.InternalCall)]
500 extern private static void ClrState (InternalThread thread, ThreadState clr);
502 [MethodImplAttribute (MethodImplOptions.InternalCall)]
503 extern private static ThreadState GetState (InternalThread thread);
505 [MethodImplAttribute (MethodImplOptions.InternalCall)]
506 extern public static byte VolatileRead (ref byte address);
508 [MethodImplAttribute (MethodImplOptions.InternalCall)]
509 extern public static double VolatileRead (ref double address);
511 [MethodImplAttribute (MethodImplOptions.InternalCall)]
512 extern public static short VolatileRead (ref short address);
514 [MethodImplAttribute (MethodImplOptions.InternalCall)]
515 extern public static int VolatileRead (ref int address);
517 [MethodImplAttribute (MethodImplOptions.InternalCall)]
518 extern public static long VolatileRead (ref long address);
520 [MethodImplAttribute (MethodImplOptions.InternalCall)]
521 extern public static IntPtr VolatileRead (ref IntPtr address);
523 [MethodImplAttribute (MethodImplOptions.InternalCall)]
524 extern public static object VolatileRead (ref object address);
526 [CLSCompliant(false)]
527 [MethodImplAttribute (MethodImplOptions.InternalCall)]
528 extern public static sbyte VolatileRead (ref sbyte address);
530 [MethodImplAttribute (MethodImplOptions.InternalCall)]
531 extern public static float VolatileRead (ref float address);
533 [CLSCompliant (false)]
534 [MethodImplAttribute (MethodImplOptions.InternalCall)]
535 extern public static ushort VolatileRead (ref ushort address);
537 [CLSCompliant (false)]
538 [MethodImplAttribute (MethodImplOptions.InternalCall)]
539 extern public static uint VolatileRead (ref uint address);
541 [CLSCompliant (false)]
542 [MethodImplAttribute (MethodImplOptions.InternalCall)]
543 extern public static ulong VolatileRead (ref ulong address);
545 [CLSCompliant (false)]
546 [MethodImplAttribute (MethodImplOptions.InternalCall)]
547 extern public static UIntPtr VolatileRead (ref UIntPtr address);
549 [MethodImplAttribute (MethodImplOptions.InternalCall)]
550 extern public static void VolatileWrite (ref byte address, byte value);
552 [MethodImplAttribute (MethodImplOptions.InternalCall)]
553 extern public static void VolatileWrite (ref double address, double value);
555 [MethodImplAttribute (MethodImplOptions.InternalCall)]
556 extern public static void VolatileWrite (ref short address, short value);
558 [MethodImplAttribute (MethodImplOptions.InternalCall)]
559 extern public static void VolatileWrite (ref int address, int value);
561 [MethodImplAttribute (MethodImplOptions.InternalCall)]
562 extern public static void VolatileWrite (ref long address, long value);
564 [MethodImplAttribute (MethodImplOptions.InternalCall)]
565 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
567 [MethodImplAttribute (MethodImplOptions.InternalCall)]
568 extern public static void VolatileWrite (ref object address, object value);
570 [CLSCompliant(false)]
571 [MethodImplAttribute (MethodImplOptions.InternalCall)]
572 extern public static void VolatileWrite (ref sbyte address, sbyte value);
574 [MethodImplAttribute (MethodImplOptions.InternalCall)]
575 extern public static void VolatileWrite (ref float address, float value);
577 [CLSCompliant (false)]
578 [MethodImplAttribute (MethodImplOptions.InternalCall)]
579 extern public static void VolatileWrite (ref ushort address, ushort value);
581 [CLSCompliant (false)]
582 [MethodImplAttribute (MethodImplOptions.InternalCall)]
583 extern public static void VolatileWrite (ref uint address, uint value);
585 [CLSCompliant (false)]
586 [MethodImplAttribute (MethodImplOptions.InternalCall)]
587 extern public static void VolatileWrite (ref ulong address, ulong value);
589 [CLSCompliant (false)]
590 [MethodImplAttribute (MethodImplOptions.InternalCall)]
591 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
593 [MethodImplAttribute (MethodImplOptions.InternalCall)]
594 extern static int SystemMaxStackStize ();
596 static int GetProcessDefaultStackSize (int maxStackSize)
598 if (maxStackSize == 0)
601 if (maxStackSize < 131072) // make sure stack is at least 128k big
604 int page_size = Environment.GetPageSize ();
606 if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
607 maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
609 /* Respect the max stack size imposed by the system*/
610 return Math.Min (maxStackSize, SystemMaxStackStize ());
613 void SetStart (MulticastDelegate start, int maxStackSize)
616 Internal.stack_size = maxStackSize;
619 public int ManagedThreadId {
620 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
622 return Internal.managed_id;
626 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
627 public static void BeginCriticalRegion ()
629 CurrentThread.Internal.critical_region_level++;
632 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
633 public static void EndCriticalRegion ()
635 CurrentThread.Internal.critical_region_level--;
638 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
639 public static void BeginThreadAffinity ()
641 // Managed and native threads are currently bound together.
644 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
645 public static void EndThreadAffinity ()
647 // Managed and native threads are currently bound together.
650 public ApartmentState GetApartmentState ()
652 return (ApartmentState)Internal.apartment_state;
655 public void SetApartmentState (ApartmentState state)
657 if (!TrySetApartmentState (state))
658 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
661 public bool TrySetApartmentState (ApartmentState state)
663 if ((ThreadState & ThreadState.Unstarted) == 0)
664 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
666 if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown &&
667 (ApartmentState)Internal.apartment_state != state)
670 Internal.apartment_state = (byte)state;
676 public override int GetHashCode ()
678 return ManagedThreadId;
681 [MethodImplAttribute(MethodImplOptions.InternalCall)]
682 internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
684 // This is a mono extension to gather the stack traces for all running threads
685 internal static Dictionary<Thread, StackTrace> Mono_GetStackTraces () {
687 object[] stack_frames;
689 GetStackTraces (out threads, out stack_frames);
691 var res = new Dictionary<Thread, StackTrace> ();
692 for (int i = 0; i < threads.Length; ++i)
693 res [threads [i]] = new StackTrace ((StackFrame[])stack_frames [i]);
697 #if !MONO_FEATURE_THREAD_SUSPEND_RESUME
698 [Obsolete ("Thread.Suspend is not supported on the current platform.", true)]
699 public void Suspend ()
701 throw new PlatformNotSupportedException ("Thread.Suspend is not supported on the current platform.");
704 [Obsolete ("Thread.Resume is not supported on the current platform.", true)]
705 public void Resume ()
707 throw new PlatformNotSupportedException ("Thread.Resume is not supported on the current platform.");
711 public void DisableComObjectEagerCleanup ()
713 throw new PlatformNotSupportedException ();