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;
40 using System.Security;
43 using System.Runtime.ConstrainedExecution;
46 namespace System.Threading {
48 [ClassInterface (ClassInterfaceType.None)]
51 [ComDefaultInterface (typeof (_Thread))]
52 public sealed class Thread : CriticalFinalizerObject, _Thread {
54 public sealed class Thread : _Thread {
57 #pragma warning disable 169, 414
58 #region Sync with metadata/object-internals.h
60 // stores a thread handle
61 private IntPtr system_thread_handle;
63 /* Note this is an opaque object (an array), not a CultureInfo */
64 private object cached_culture_info;
65 private IntPtr unused0;
66 private bool threadpool_thread;
67 /* accessed only from unmanaged code */
70 private ThreadState state = ThreadState.Unstarted;
71 private object abort_exc;
72 internal object abort_state;
73 /* thread_id is only accessed from unmanaged code */
74 private Int64 thread_id;
76 /* start_notify is used by the runtime to signal that Start()
79 private IntPtr start_notify;
80 private IntPtr stack_ptr;
81 private UIntPtr static_data; /* GC-tracked */
82 private IntPtr jit_data;
83 private IntPtr lock_data;
84 Context current_appcontext;
87 private IntPtr appdomain_refs;
88 private int interruption_requested;
89 private IntPtr suspend_event;
90 private IntPtr suspended_event;
91 private IntPtr resume_event;
92 private IntPtr synch_cs;
93 private IntPtr serialized_culture_info;
94 private int serialized_culture_info_len;
95 private IntPtr serialized_ui_culture_info;
96 private int serialized_ui_culture_info_len;
97 private ExecutionContext _ec;
98 private bool thread_dump_requested;
99 private IntPtr end_stack;
100 private bool thread_interrupt_requested;
101 private byte apartment_state = (byte)ApartmentState.Unknown;
102 volatile int critical_region_level;
103 private int small_id;
104 private IntPtr manage_callback;
105 private object pending_exception;
107 * These fields are used to avoid having to increment corlib versions
108 * when a new field is added to the unmanaged MonoThread structure.
110 private IntPtr unused2;
111 private IntPtr unused3;
112 private IntPtr unused4;
113 private IntPtr unused5;
114 private IntPtr unused6;
116 #pragma warning restore 169, 414
118 // the name of local_slots is important as it's used by the runtime.
120 static object[] local_slots;
122 // can be both a ThreadSart and a ParameterizedThreadStart
123 private MulticastDelegate threadstart;
124 //private string thread_name=null;
127 private static int _managed_id_counter;
128 private int managed_id;
131 private IPrincipal _principal;
132 internal NumberFormatter _numberFormatter;
134 public static Context CurrentContext {
135 [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
137 return(AppDomain.InternalGetContext ());
141 public static IPrincipal CurrentPrincipal {
144 Thread th = CurrentThread;
148 p = GetDomain ().DefaultPrincipal;
154 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
156 CurrentThread._principal = value;
160 // Looks up the object associated with the current thread
161 [MethodImplAttribute(MethodImplOptions.InternalCall)]
162 private extern static Thread CurrentThread_internal();
164 public static Thread CurrentThread {
166 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
169 return(CurrentThread_internal());
173 internal static int CurrentThreadId {
175 return (int)(CurrentThread.thread_id);
179 // Stores a hash keyed by strings of LocalDataStoreSlot objects
180 static Hashtable datastorehash;
181 private static object datastore_lock = new object ();
183 private static void InitDataStoreHash () {
184 lock (datastore_lock) {
185 if (datastorehash == null) {
186 datastorehash = Hashtable.Synchronized(new Hashtable());
191 public static LocalDataStoreSlot AllocateNamedDataSlot (string name) {
192 lock (datastore_lock) {
193 if (datastorehash == null)
194 InitDataStoreHash ();
195 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
197 // This exception isnt documented (of
198 // course) but .net throws it
199 throw new ArgumentException("Named data slot already added");
202 slot = AllocateDataSlot ();
204 datastorehash.Add (name, slot);
210 public static void FreeNamedDataSlot (string name) {
211 lock (datastore_lock) {
212 if (datastorehash == null)
213 InitDataStoreHash ();
214 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
217 datastorehash.Remove (slot);
222 public static LocalDataStoreSlot AllocateDataSlot () {
223 return new LocalDataStoreSlot (true);
226 public static object GetData (LocalDataStoreSlot slot) {
227 object[] slots = local_slots;
229 throw new ArgumentNullException ("slot");
230 if (slots != null && slot.slot < slots.Length)
231 return slots [slot.slot];
235 public static void SetData (LocalDataStoreSlot slot, object data) {
236 object[] slots = local_slots;
238 throw new ArgumentNullException ("slot");
240 slots = new object [slot.slot + 2];
242 } else if (slot.slot >= slots.Length) {
243 object[] nslots = new object [slot.slot + 2];
244 slots.CopyTo (nslots, 0);
248 slots [slot.slot] = data;
251 internal NumberFormatter AcquireNumberFormatter() {
252 NumberFormatter res = _numberFormatter;
253 _numberFormatter = null;
255 return new NumberFormatter (this);
259 internal void ReleaseNumberFormatter (NumberFormatter formatter) {
260 _numberFormatter = formatter;
263 public static AppDomain GetDomain() {
264 return AppDomain.CurrentDomain;
267 [MethodImplAttribute(MethodImplOptions.InternalCall)]
268 public extern static int GetDomainID();
270 [MethodImplAttribute (MethodImplOptions.InternalCall)]
271 internal extern static void FreeLocalSlotValues (int slot, bool thread_local);
273 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
274 lock (datastore_lock) {
275 if (datastorehash == null)
276 InitDataStoreHash ();
277 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
280 slot=AllocateNamedDataSlot(name);
287 [MethodImplAttribute(MethodImplOptions.InternalCall)]
288 private extern static void ResetAbort_internal();
290 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
291 public static void ResetAbort ()
293 ResetAbort_internal ();
296 [MethodImplAttribute(MethodImplOptions.InternalCall)]
297 private extern static void Sleep_internal(int ms);
299 public static void Sleep(int millisecondsTimeout) {
300 if((millisecondsTimeout<0) && (millisecondsTimeout != Timeout.Infinite)) {
301 throw new ArgumentException("Negative timeout");
303 Sleep_internal(millisecondsTimeout);
306 public static void Sleep(TimeSpan timeout) {
307 // LAMESPEC: says to throw ArgumentException too
308 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
310 if(ms < 0 || ms > Int32.MaxValue) {
311 throw new ArgumentOutOfRangeException("Timeout out of range");
317 // Returns the system thread handle
318 [MethodImplAttribute(MethodImplOptions.InternalCall)]
319 private extern IntPtr Thread_internal (MulticastDelegate start);
321 [MethodImplAttribute(MethodImplOptions.InternalCall)]
322 private extern void Thread_init ();
324 public Thread(ThreadStart start) {
326 throw new ArgumentNullException("Null ThreadStart");
334 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
336 public ApartmentState ApartmentState {
338 if ((ThreadState & ThreadState.Stopped) != 0)
339 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
341 return (ApartmentState)apartment_state;
346 TrySetApartmentState (value);
348 /* Only throw this exception when
349 * changing the state of another
350 * thread. See bug 324338
352 if ((this != CurrentThread) &&
353 (ThreadState & ThreadState.Unstarted) == 0)
354 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
356 if (value != ApartmentState.STA && value != ApartmentState.MTA)
357 throw new ArgumentOutOfRangeException ("value is not a valid apartment state.");
359 if ((ApartmentState)apartment_state == ApartmentState.Unknown)
360 apartment_state = (byte)value;
365 //[MethodImplAttribute (MethodImplOptions.InternalCall)]
366 //private static extern int current_lcid ();
368 [MethodImplAttribute (MethodImplOptions.InternalCall)]
369 private extern CultureInfo GetCachedCurrentCulture ();
371 [MethodImplAttribute (MethodImplOptions.InternalCall)]
372 private extern byte[] GetSerializedCurrentCulture ();
374 [MethodImplAttribute (MethodImplOptions.InternalCall)]
375 private extern void SetCachedCurrentCulture (CultureInfo culture);
377 [MethodImplAttribute (MethodImplOptions.InternalCall)]
378 private extern void SetSerializedCurrentCulture (byte[] culture);
380 [MethodImplAttribute (MethodImplOptions.InternalCall)]
381 private extern CultureInfo GetCachedCurrentUICulture ();
383 [MethodImplAttribute (MethodImplOptions.InternalCall)]
384 private extern byte[] GetSerializedCurrentUICulture ();
386 [MethodImplAttribute (MethodImplOptions.InternalCall)]
387 private extern void SetCachedCurrentUICulture (CultureInfo culture);
389 [MethodImplAttribute (MethodImplOptions.InternalCall)]
390 private extern void SetSerializedCurrentUICulture (byte[] culture);
392 /* If the current_lcid() isn't known by CultureInfo,
393 * it will throw an exception which may cause
394 * String.Concat to try and recursively look up the
395 * CurrentCulture, which will throw an exception, etc.
396 * Use a boolean to short-circuit this scenario.
398 private bool in_currentculture=false;
400 static object culture_lock = new object ();
403 * Thread objects are shared between appdomains, and CurrentCulture
404 * should always return an object in the calling appdomain. See bug
405 * http://bugzilla.ximian.com/show_bug.cgi?id=50049 for more info.
406 * This is hard to implement correctly and efficiently, so the current
407 * implementation is not perfect: changes made in one appdomain to the
408 * state of the current cultureinfo object are not visible to other
411 public CultureInfo CurrentCulture {
413 if (in_currentculture)
415 return CultureInfo.InvariantCulture;
417 CultureInfo culture = GetCachedCurrentCulture ();
421 byte[] arr = GetSerializedCurrentCulture ();
423 lock (culture_lock) {
424 in_currentculture=true;
425 culture = CultureInfo.ConstructCurrentCulture ();
427 // Don't serialize the culture in this case to avoid
428 // initializing the serialization infrastructure in the
429 // common case when the culture is not set explicitly.
431 SetCachedCurrentCulture (culture);
432 in_currentculture = false;
433 if (_numberFormatter != null)
434 _numberFormatter.CurrentCulture = culture;
440 * No cultureinfo object exists for this domain, so create one
441 * by deserializing the serialized form.
443 in_currentculture = true;
445 BinaryFormatter bf = new BinaryFormatter ();
446 MemoryStream ms = new MemoryStream (arr);
447 culture = (CultureInfo)bf.Deserialize (ms);
448 SetCachedCurrentCulture (culture);
450 in_currentculture = false;
453 if (_numberFormatter != null)
454 _numberFormatter.CurrentCulture = culture;
458 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
461 throw new ArgumentNullException ("value");
463 CultureInfo culture = GetCachedCurrentCulture ();
464 if (culture == value)
467 value.CheckNeutral ();
468 in_currentculture = true;
470 SetCachedCurrentCulture (value);
472 byte[] serialized_form = null;
474 if (value.IsReadOnly && value.cached_serialized_form != null) {
475 serialized_form = value.cached_serialized_form;
477 BinaryFormatter bf = new BinaryFormatter();
478 MemoryStream ms = new MemoryStream ();
479 bf.Serialize (ms, value);
481 serialized_form = ms.GetBuffer ();
482 if (value.IsReadOnly)
483 value.cached_serialized_form = serialized_form;
486 SetSerializedCurrentCulture (serialized_form);
488 in_currentculture = false;
490 if (_numberFormatter != null)
491 _numberFormatter.CurrentCulture = value;
495 public CultureInfo CurrentUICulture {
497 if (in_currentculture)
499 return CultureInfo.InvariantCulture;
501 CultureInfo culture = GetCachedCurrentUICulture ();
505 byte[] arr = GetSerializedCurrentUICulture ();
507 lock (culture_lock) {
508 in_currentculture=true;
515 culture = CultureInfo.ConstructCurrentUICulture ();
517 // Don't serialize the culture in this case to avoid
518 // initializing the serialization infrastructure in the
519 // common case when the culture is not set explicitly.
521 SetCachedCurrentUICulture (culture);
522 in_currentculture = false;
528 * No cultureinfo object exists for this domain, so create one
529 * by deserializing the serialized form.
531 in_currentculture = true;
533 BinaryFormatter bf = new BinaryFormatter ();
534 MemoryStream ms = new MemoryStream (arr);
535 culture = (CultureInfo)bf.Deserialize (ms);
536 SetCachedCurrentUICulture (culture);
539 in_currentculture = false;
546 in_currentculture = true;
549 throw new ArgumentNullException ("value");
551 CultureInfo culture = GetCachedCurrentUICulture ();
552 if (culture == value)
556 SetCachedCurrentUICulture (value);
558 byte[] serialized_form = null;
560 if (value.IsReadOnly && value.cached_serialized_form != null) {
561 serialized_form = value.cached_serialized_form;
563 BinaryFormatter bf = new BinaryFormatter();
564 MemoryStream ms = new MemoryStream ();
565 bf.Serialize (ms, value);
567 serialized_form = ms.GetBuffer ();
568 if (value.IsReadOnly)
569 value.cached_serialized_form = serialized_form;
572 SetSerializedCurrentUICulture (serialized_form);
574 in_currentculture = false;
579 public bool IsThreadPoolThread {
581 return IsThreadPoolThreadInternal;
585 internal bool IsThreadPoolThreadInternal {
587 return threadpool_thread;
590 threadpool_thread = value;
594 public bool IsAlive {
596 ThreadState curstate = GetState ();
598 if((curstate & ThreadState.Aborted) != 0 ||
599 (curstate & ThreadState.Stopped) != 0 ||
600 (curstate & ThreadState.Unstarted) != 0) {
608 public bool IsBackground {
610 ThreadState thread_state = GetState ();
611 if ((thread_state & ThreadState.Stopped) != 0)
612 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
614 return (thread_state & ThreadState.Background) != 0;
619 SetState (ThreadState.Background);
621 ClrState (ThreadState.Background);
626 [MethodImplAttribute(MethodImplOptions.InternalCall)]
627 private extern string GetName_internal ();
629 [MethodImplAttribute(MethodImplOptions.InternalCall)]
630 private extern void SetName_internal (String name);
633 * The thread name must be shared by appdomains, so it is stored in
639 return GetName_internal ();
643 SetName_internal (value);
647 public ThreadPriority Priority {
649 return(ThreadPriority.Lowest);
653 // FIXME: Implement setter.
657 public ThreadState ThreadState {
663 [MethodImplAttribute(MethodImplOptions.InternalCall)]
664 private extern void Abort_internal (object stateInfo);
666 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
669 Abort_internal (null);
672 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
673 public void Abort (object stateInfo)
675 Abort_internal (stateInfo);
678 [MethodImplAttribute (MethodImplOptions.InternalCall)]
679 private extern void Interrupt_internal ();
681 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
682 public void Interrupt ()
684 Interrupt_internal ();
687 // The current thread joins with 'this'. Set ms to 0 to block
688 // until this actually exits.
689 [MethodImplAttribute(MethodImplOptions.InternalCall)]
690 private extern bool Join_internal(int ms, IntPtr handle);
694 Join_internal(Timeout.Infinite, system_thread_handle);
697 public bool Join(int millisecondsTimeout)
699 if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
700 throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
702 return Join_internal(millisecondsTimeout, system_thread_handle);
705 public bool Join(TimeSpan timeout)
707 // LAMESPEC: says to throw ArgumentException too
708 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
710 if(ms < 0 || ms > Int32.MaxValue) {
711 throw new ArgumentOutOfRangeException("timeout out of range");
713 return Join_internal(ms, system_thread_handle);
717 [MethodImplAttribute(MethodImplOptions.InternalCall)]
718 public extern static void MemoryBarrier ();
720 [MethodImplAttribute(MethodImplOptions.InternalCall)]
721 private extern void Resume_internal();
726 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
727 public void Resume ()
732 [MethodImplAttribute (MethodImplOptions.InternalCall)]
733 private extern static void SpinWait_internal (int iterations);
737 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
739 public static void SpinWait (int iterations)
741 SpinWait_internal (iterations);
744 public void Start() {
745 // propagate informations from the original thread to the new thread
747 if (!ExecutionContext.IsFlowSuppressed ())
748 _ec = ExecutionContext.Capture ();
750 // before 2.0 this was only used for security (mostly CAS) so we
751 // do this only if the security manager is active
752 if (SecurityManager.SecurityEnabled)
753 _ec = ExecutionContext.Capture ();
755 if (CurrentThread._principal != null)
756 _principal = CurrentThread._principal;
758 // Thread_internal creates and starts the new thread,
759 if (Thread_internal(threadstart) == (IntPtr) 0)
760 throw new SystemException ("Thread creation failed.");
763 [MethodImplAttribute(MethodImplOptions.InternalCall)]
764 private extern void Suspend_internal();
769 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
770 public void Suspend ()
775 // Closes the system thread handle
776 [MethodImplAttribute(MethodImplOptions.InternalCall)]
777 private extern void Thread_free_internal(IntPtr handle);
780 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
783 // Free up the handle
784 if (system_thread_handle != (IntPtr) 0)
785 Thread_free_internal(system_thread_handle);
788 [MethodImplAttribute (MethodImplOptions.InternalCall)]
789 extern private void SetState (ThreadState set);
791 [MethodImplAttribute (MethodImplOptions.InternalCall)]
792 extern private void ClrState (ThreadState clr);
794 [MethodImplAttribute (MethodImplOptions.InternalCall)]
795 extern private ThreadState GetState ();
799 [MethodImplAttribute (MethodImplOptions.InternalCall)]
800 extern public static byte VolatileRead (ref byte address);
802 [MethodImplAttribute (MethodImplOptions.InternalCall)]
803 extern public static double VolatileRead (ref double address);
805 [MethodImplAttribute (MethodImplOptions.InternalCall)]
806 extern public static short VolatileRead (ref short address);
808 [MethodImplAttribute (MethodImplOptions.InternalCall)]
809 extern public static int VolatileRead (ref int address);
811 [MethodImplAttribute (MethodImplOptions.InternalCall)]
812 extern public static long VolatileRead (ref long address);
814 [MethodImplAttribute (MethodImplOptions.InternalCall)]
815 extern public static IntPtr VolatileRead (ref IntPtr address);
817 [MethodImplAttribute (MethodImplOptions.InternalCall)]
818 extern public static object VolatileRead (ref object address);
820 [CLSCompliant(false)]
821 [MethodImplAttribute (MethodImplOptions.InternalCall)]
822 extern public static sbyte VolatileRead (ref sbyte address);
824 [MethodImplAttribute (MethodImplOptions.InternalCall)]
825 extern public static float VolatileRead (ref float address);
827 [CLSCompliant (false)]
828 [MethodImplAttribute (MethodImplOptions.InternalCall)]
829 extern public static ushort VolatileRead (ref ushort address);
831 [CLSCompliant (false)]
832 [MethodImplAttribute (MethodImplOptions.InternalCall)]
833 extern public static uint VolatileRead (ref uint address);
835 [CLSCompliant (false)]
836 [MethodImplAttribute (MethodImplOptions.InternalCall)]
837 extern public static ulong VolatileRead (ref ulong address);
839 [CLSCompliant (false)]
840 [MethodImplAttribute (MethodImplOptions.InternalCall)]
841 extern public static UIntPtr VolatileRead (ref UIntPtr address);
843 [MethodImplAttribute (MethodImplOptions.InternalCall)]
844 extern public static void VolatileWrite (ref byte address, byte value);
846 [MethodImplAttribute (MethodImplOptions.InternalCall)]
847 extern public static void VolatileWrite (ref double address, double value);
849 [MethodImplAttribute (MethodImplOptions.InternalCall)]
850 extern public static void VolatileWrite (ref short address, short value);
852 [MethodImplAttribute (MethodImplOptions.InternalCall)]
853 extern public static void VolatileWrite (ref int address, int value);
855 [MethodImplAttribute (MethodImplOptions.InternalCall)]
856 extern public static void VolatileWrite (ref long address, long value);
858 [MethodImplAttribute (MethodImplOptions.InternalCall)]
859 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
861 [MethodImplAttribute (MethodImplOptions.InternalCall)]
862 extern public static void VolatileWrite (ref object address, object value);
864 [CLSCompliant(false)]
865 [MethodImplAttribute (MethodImplOptions.InternalCall)]
866 extern public static void VolatileWrite (ref sbyte address, sbyte value);
868 [MethodImplAttribute (MethodImplOptions.InternalCall)]
869 extern public static void VolatileWrite (ref float address, float value);
871 [CLSCompliant (false)]
872 [MethodImplAttribute (MethodImplOptions.InternalCall)]
873 extern public static void VolatileWrite (ref ushort address, ushort value);
875 [CLSCompliant (false)]
876 [MethodImplAttribute (MethodImplOptions.InternalCall)]
877 extern public static void VolatileWrite (ref uint address, uint value);
879 [CLSCompliant (false)]
880 [MethodImplAttribute (MethodImplOptions.InternalCall)]
881 extern public static void VolatileWrite (ref ulong address, ulong value);
883 [CLSCompliant (false)]
884 [MethodImplAttribute (MethodImplOptions.InternalCall)]
885 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
890 private static int GetNewManagedId() {
891 return Interlocked.Increment(ref _managed_id_counter);
894 public Thread (ThreadStart start, int maxStackSize)
897 throw new ArgumentNullException ("start");
898 if (maxStackSize < 131072)
899 throw new ArgumentException ("< 128 kb", "maxStackSize");
902 stack_size = maxStackSize;
906 public Thread (ParameterizedThreadStart start)
909 throw new ArgumentNullException ("start");
915 public Thread (ParameterizedThreadStart start, int maxStackSize)
918 throw new ArgumentNullException ("start");
919 if (maxStackSize < 131072)
920 throw new ArgumentException ("< 128 kb", "maxStackSize");
923 stack_size = maxStackSize;
927 [MonoTODO ("limited to CompressedStack support")]
928 // FIXME: We share the _ec object between appdomains
929 public ExecutionContext ExecutionContext {
930 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
933 _ec = new ExecutionContext ();
938 public int ManagedThreadId {
939 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
941 if (managed_id == 0) {
942 int new_managed_id = GetNewManagedId ();
944 Interlocked.CompareExchange (ref managed_id, new_managed_id, 0);
951 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
952 public static void BeginCriticalRegion ()
954 CurrentThread.critical_region_level++;
957 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
958 public static void EndCriticalRegion ()
960 CurrentThread.critical_region_level--;
963 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
964 public static void BeginThreadAffinity ()
966 // Managed and native threads are currently bound together.
969 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
970 public static void EndThreadAffinity ()
972 // Managed and native threads are currently bound together.
975 public ApartmentState GetApartmentState ()
977 return (ApartmentState)apartment_state;
980 public void SetApartmentState (ApartmentState state)
982 if (!TrySetApartmentState (state))
983 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
986 public bool TrySetApartmentState (ApartmentState state)
988 /* Only throw this exception when changing the
989 * state of another thread. See bug 324338
991 if ((this != CurrentThread) &&
992 (ThreadState & ThreadState.Unstarted) == 0)
993 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
995 if ((ApartmentState)apartment_state != ApartmentState.Unknown)
998 apartment_state = (byte)state;
1003 [ComVisible (false)]
1004 public override int GetHashCode ()
1006 return ManagedThreadId;
1009 public void Start (object parameter)
1011 start_obj = parameter;
1015 internal ExecutionContext ExecutionContext {
1018 _ec = new ExecutionContext ();
1024 // NOTE: This method doesn't show in the class library status page because
1025 // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
1027 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
1028 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
1030 [Obsolete ("see CompressedStack class")]
1037 CompressedStack GetCompressedStack ()
1039 // Note: returns null if no CompressedStack has been set.
1040 // However CompressedStack.GetCompressedStack returns an
1041 // (empty?) CompressedStack instance.
1042 CompressedStack cs = ExecutionContext.SecurityContext.CompressedStack;
1043 return ((cs == null) || cs.IsEmpty ()) ? null : cs.CreateCopy ();
1046 // NOTE: This method doesn't show in the class library status page because
1047 // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
1049 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
1050 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
1052 [Obsolete ("see CompressedStack class")]
1059 void SetCompressedStack (CompressedStack stack)
1061 ExecutionContext.SecurityContext.CompressedStack = stack;
1065 void _Thread.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1067 throw new NotImplementedException ();
1070 void _Thread.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1072 throw new NotImplementedException ();
1075 void _Thread.GetTypeInfoCount (out uint pcTInfo)
1077 throw new NotImplementedException ();
1080 void _Thread.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
1081 IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1083 throw new NotImplementedException ();