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.Reflection;
41 using System.Security;
44 using System.Runtime.ConstrainedExecution;
47 namespace System.Threading {
49 [ClassInterface (ClassInterfaceType.None)]
52 [ComDefaultInterface (typeof (_Thread))]
53 public sealed class Thread : CriticalFinalizerObject, _Thread {
55 public sealed class Thread : _Thread {
58 #pragma warning disable 169, 414, 649
59 #region Sync with metadata/object-internals.h
61 // stores a thread handle
62 private IntPtr system_thread_handle;
64 /* Note this is an opaque object (an array), not a CultureInfo */
65 private object cached_culture_info;
66 private IntPtr unused0;
67 private bool threadpool_thread;
68 /* accessed only from unmanaged code */
71 private ThreadState state = ThreadState.Unstarted;
72 private object abort_exc;
73 private int abort_state_handle;
74 /* thread_id is only accessed from unmanaged code */
75 private Int64 thread_id;
77 /* start_notify is used by the runtime to signal that Start()
80 private IntPtr start_notify;
81 private IntPtr stack_ptr;
82 private UIntPtr static_data; /* GC-tracked */
83 private IntPtr jit_data;
84 private IntPtr lock_data;
85 Context current_appcontext;
88 private IntPtr appdomain_refs;
89 private int interruption_requested;
90 private IntPtr suspend_event;
91 private IntPtr suspended_event;
92 private IntPtr resume_event;
93 private IntPtr synch_cs;
94 private IntPtr serialized_culture_info;
95 private int serialized_culture_info_len;
96 private IntPtr serialized_ui_culture_info;
97 private int serialized_ui_culture_info_len;
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;
106 /* This is the ExecutionContext that will be set by
107 start_wrapper() in the runtime. */
108 private ExecutionContext ec_to_set;
111 * These fields are used to avoid having to increment corlib versions
112 * when a new field is added to the unmanaged MonoThread structure.
114 private IntPtr unused2;
115 private IntPtr unused3;
116 private IntPtr unused4;
117 private IntPtr unused5;
118 private IntPtr unused6;
120 #pragma warning restore 169, 414, 649
122 // the name of local_slots is important as it's used by the runtime.
124 static object[] local_slots;
126 /* The actual ExecutionContext of the thread. It's
127 ThreadStatic so that it's not shared between
130 static ExecutionContext _ec;
132 // can be both a ThreadSart and a ParameterizedThreadStart
133 private MulticastDelegate threadstart;
134 //private string thread_name=null;
137 private static int _managed_id_counter;
138 private int managed_id;
141 private IPrincipal _principal;
143 public static Context CurrentContext {
144 [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
146 return(AppDomain.InternalGetContext ());
150 public static IPrincipal CurrentPrincipal {
153 Thread th = CurrentThread;
157 p = GetDomain ().DefaultPrincipal;
163 [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
165 CurrentThread._principal = value;
169 // Looks up the object associated with the current thread
170 [MethodImplAttribute(MethodImplOptions.InternalCall)]
171 private extern static Thread CurrentThread_internal();
173 public static Thread CurrentThread {
175 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
178 return(CurrentThread_internal());
182 internal static int CurrentThreadId {
184 return (int)(CurrentThread.thread_id);
188 // Stores a hash keyed by strings of LocalDataStoreSlot objects
189 static Hashtable datastorehash;
190 private static object datastore_lock = new object ();
192 private static void InitDataStoreHash () {
193 lock (datastore_lock) {
194 if (datastorehash == null) {
195 datastorehash = Hashtable.Synchronized(new Hashtable());
200 public static LocalDataStoreSlot AllocateNamedDataSlot (string name) {
201 lock (datastore_lock) {
202 if (datastorehash == null)
203 InitDataStoreHash ();
204 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
206 // This exception isnt documented (of
207 // course) but .net throws it
208 throw new ArgumentException("Named data slot already added");
211 slot = AllocateDataSlot ();
213 datastorehash.Add (name, slot);
219 public static void FreeNamedDataSlot (string name) {
220 lock (datastore_lock) {
221 if (datastorehash == null)
222 InitDataStoreHash ();
223 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
226 datastorehash.Remove (slot);
231 public static LocalDataStoreSlot AllocateDataSlot () {
232 return new LocalDataStoreSlot (true);
235 public static object GetData (LocalDataStoreSlot slot) {
236 object[] slots = local_slots;
238 throw new ArgumentNullException ("slot");
239 if (slots != null && slot.slot < slots.Length)
240 return slots [slot.slot];
244 public static void SetData (LocalDataStoreSlot slot, object data) {
245 object[] slots = local_slots;
247 throw new ArgumentNullException ("slot");
249 slots = new object [slot.slot + 2];
251 } else if (slot.slot >= slots.Length) {
252 object[] nslots = new object [slot.slot + 2];
253 slots.CopyTo (nslots, 0);
257 slots [slot.slot] = data;
260 public static AppDomain GetDomain() {
261 return AppDomain.CurrentDomain;
264 [MethodImplAttribute(MethodImplOptions.InternalCall)]
265 public extern static int GetDomainID();
267 [MethodImplAttribute (MethodImplOptions.InternalCall)]
268 internal extern static void FreeLocalSlotValues (int slot, bool thread_local);
270 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
271 lock (datastore_lock) {
272 if (datastorehash == null)
273 InitDataStoreHash ();
274 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
277 slot=AllocateNamedDataSlot(name);
284 [MethodImplAttribute(MethodImplOptions.InternalCall)]
285 private extern static void ResetAbort_internal();
287 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
288 public static void ResetAbort ()
290 ResetAbort_internal ();
293 [MethodImplAttribute(MethodImplOptions.InternalCall)]
294 private extern static void Sleep_internal(int ms);
296 public static void Sleep(int millisecondsTimeout) {
297 if((millisecondsTimeout<0) && (millisecondsTimeout != Timeout.Infinite)) {
298 throw new ArgumentException("Negative timeout");
300 Sleep_internal(millisecondsTimeout);
303 public static void Sleep(TimeSpan timeout) {
304 // LAMESPEC: says to throw ArgumentException too
305 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
307 if(ms < 0 || ms > Int32.MaxValue) {
308 throw new ArgumentOutOfRangeException("Timeout out of range");
314 // Returns the system thread handle
315 [MethodImplAttribute(MethodImplOptions.InternalCall)]
316 private extern IntPtr Thread_internal (MulticastDelegate start);
318 [MethodImplAttribute(MethodImplOptions.InternalCall)]
319 private extern void Thread_init ();
321 public Thread(ThreadStart start) {
323 throw new ArgumentNullException("Null ThreadStart");
331 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
333 public ApartmentState ApartmentState {
335 if ((ThreadState & ThreadState.Stopped) != 0)
336 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
338 return (ApartmentState)apartment_state;
343 TrySetApartmentState (value);
345 /* Only throw this exception when
346 * changing the state of another
347 * thread. See bug 324338
349 if ((this != CurrentThread) &&
350 (ThreadState & ThreadState.Unstarted) == 0)
351 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
353 if (value != ApartmentState.STA && value != ApartmentState.MTA)
354 throw new ArgumentOutOfRangeException ("value is not a valid apartment state.");
356 if ((ApartmentState)apartment_state == ApartmentState.Unknown)
357 apartment_state = (byte)value;
362 //[MethodImplAttribute (MethodImplOptions.InternalCall)]
363 //private static extern int current_lcid ();
365 [MethodImplAttribute (MethodImplOptions.InternalCall)]
366 private extern CultureInfo GetCachedCurrentCulture ();
368 [MethodImplAttribute (MethodImplOptions.InternalCall)]
369 private extern byte[] GetSerializedCurrentCulture ();
371 [MethodImplAttribute (MethodImplOptions.InternalCall)]
372 private extern void SetCachedCurrentCulture (CultureInfo culture);
374 [MethodImplAttribute (MethodImplOptions.InternalCall)]
375 private extern void SetSerializedCurrentCulture (byte[] culture);
377 [MethodImplAttribute (MethodImplOptions.InternalCall)]
378 private extern CultureInfo GetCachedCurrentUICulture ();
380 [MethodImplAttribute (MethodImplOptions.InternalCall)]
381 private extern byte[] GetSerializedCurrentUICulture ();
383 [MethodImplAttribute (MethodImplOptions.InternalCall)]
384 private extern void SetCachedCurrentUICulture (CultureInfo culture);
386 [MethodImplAttribute (MethodImplOptions.InternalCall)]
387 private extern void SetSerializedCurrentUICulture (byte[] culture);
389 /* If the current_lcid() isn't known by CultureInfo,
390 * it will throw an exception which may cause
391 * String.Concat to try and recursively look up the
392 * CurrentCulture, which will throw an exception, etc.
393 * Use a boolean to short-circuit this scenario.
395 private bool in_currentculture=false;
397 static object culture_lock = new object ();
400 * Thread objects are shared between appdomains, and CurrentCulture
401 * should always return an object in the calling appdomain. See bug
402 * http://bugzilla.ximian.com/show_bug.cgi?id=50049 for more info.
403 * This is hard to implement correctly and efficiently, so the current
404 * implementation is not perfect: changes made in one appdomain to the
405 * state of the current cultureinfo object are not visible to other
408 public CultureInfo CurrentCulture {
410 if (in_currentculture)
412 return CultureInfo.InvariantCulture;
414 CultureInfo culture = GetCachedCurrentCulture ();
418 byte[] arr = GetSerializedCurrentCulture ();
420 lock (culture_lock) {
421 in_currentculture=true;
422 culture = CultureInfo.ConstructCurrentCulture ();
424 // Don't serialize the culture in this case to avoid
425 // initializing the serialization infrastructure in the
426 // common case when the culture is not set explicitly.
428 SetCachedCurrentCulture (culture);
429 in_currentculture = false;
430 NumberFormatter.SetThreadCurrentCulture (culture);
436 * No cultureinfo object exists for this domain, so create one
437 * by deserializing the serialized form.
439 in_currentculture = true;
441 BinaryFormatter bf = new BinaryFormatter ();
442 MemoryStream ms = new MemoryStream (arr);
443 culture = (CultureInfo)bf.Deserialize (ms);
444 SetCachedCurrentCulture (culture);
446 in_currentculture = false;
449 NumberFormatter.SetThreadCurrentCulture (culture);
453 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
456 throw new ArgumentNullException ("value");
458 CultureInfo culture = GetCachedCurrentCulture ();
459 if (culture == value)
462 value.CheckNeutral ();
463 in_currentculture = true;
465 SetCachedCurrentCulture (value);
467 byte[] serialized_form = null;
469 if (value.IsReadOnly && value.cached_serialized_form != null) {
470 serialized_form = value.cached_serialized_form;
472 BinaryFormatter bf = new BinaryFormatter();
473 MemoryStream ms = new MemoryStream ();
474 bf.Serialize (ms, value);
476 serialized_form = ms.GetBuffer ();
477 if (value.IsReadOnly)
478 value.cached_serialized_form = serialized_form;
481 SetSerializedCurrentCulture (serialized_form);
483 in_currentculture = false;
485 NumberFormatter.SetThreadCurrentCulture (value);
489 public CultureInfo CurrentUICulture {
491 if (in_currentculture)
493 return CultureInfo.InvariantCulture;
495 CultureInfo culture = GetCachedCurrentUICulture ();
499 byte[] arr = GetSerializedCurrentUICulture ();
501 lock (culture_lock) {
502 in_currentculture=true;
509 culture = CultureInfo.ConstructCurrentUICulture ();
511 // Don't serialize the culture in this case to avoid
512 // initializing the serialization infrastructure in the
513 // common case when the culture is not set explicitly.
515 SetCachedCurrentUICulture (culture);
516 in_currentculture = false;
522 * No cultureinfo object exists for this domain, so create one
523 * by deserializing the serialized form.
525 in_currentculture = true;
527 BinaryFormatter bf = new BinaryFormatter ();
528 MemoryStream ms = new MemoryStream (arr);
529 culture = (CultureInfo)bf.Deserialize (ms);
530 SetCachedCurrentUICulture (culture);
533 in_currentculture = false;
540 in_currentculture = true;
543 throw new ArgumentNullException ("value");
545 CultureInfo culture = GetCachedCurrentUICulture ();
546 if (culture == value)
550 SetCachedCurrentUICulture (value);
552 byte[] serialized_form = null;
554 if (value.IsReadOnly && value.cached_serialized_form != null) {
555 serialized_form = value.cached_serialized_form;
557 BinaryFormatter bf = new BinaryFormatter();
558 MemoryStream ms = new MemoryStream ();
559 bf.Serialize (ms, value);
561 serialized_form = ms.GetBuffer ();
562 if (value.IsReadOnly)
563 value.cached_serialized_form = serialized_form;
566 SetSerializedCurrentUICulture (serialized_form);
568 in_currentculture = false;
573 public bool IsThreadPoolThread {
575 return IsThreadPoolThreadInternal;
579 internal bool IsThreadPoolThreadInternal {
581 return threadpool_thread;
584 threadpool_thread = value;
588 public bool IsAlive {
590 ThreadState curstate = GetState ();
592 if((curstate & ThreadState.Aborted) != 0 ||
593 (curstate & ThreadState.Stopped) != 0 ||
594 (curstate & ThreadState.Unstarted) != 0) {
602 public bool IsBackground {
604 ThreadState thread_state = GetState ();
605 if ((thread_state & ThreadState.Stopped) != 0)
606 throw new ThreadStateException ("Thread is dead; state can not be accessed.");
608 return (thread_state & ThreadState.Background) != 0;
613 SetState (ThreadState.Background);
615 ClrState (ThreadState.Background);
620 [MethodImplAttribute(MethodImplOptions.InternalCall)]
621 private extern string GetName_internal ();
623 [MethodImplAttribute(MethodImplOptions.InternalCall)]
624 private extern void SetName_internal (String name);
627 * The thread name must be shared by appdomains, so it is stored in
633 return GetName_internal ();
637 SetName_internal (value);
641 public ThreadPriority Priority {
643 return(ThreadPriority.Lowest);
647 // FIXME: Implement setter.
651 public ThreadState ThreadState {
657 [MethodImplAttribute(MethodImplOptions.InternalCall)]
658 private extern void Abort_internal (object stateInfo);
660 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
663 Abort_internal (null);
666 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
667 public void Abort (object stateInfo)
669 Abort_internal (stateInfo);
672 [MethodImplAttribute(MethodImplOptions.InternalCall)]
673 internal extern object GetAbortExceptionState ();
675 [MethodImplAttribute (MethodImplOptions.InternalCall)]
676 private extern void Interrupt_internal ();
678 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
679 public void Interrupt ()
681 Interrupt_internal ();
684 // The current thread joins with 'this'. Set ms to 0 to block
685 // until this actually exits.
686 [MethodImplAttribute(MethodImplOptions.InternalCall)]
687 private extern bool Join_internal(int ms, IntPtr handle);
691 Join_internal(Timeout.Infinite, system_thread_handle);
694 public bool Join(int millisecondsTimeout)
696 if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
697 throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
699 return Join_internal(millisecondsTimeout, system_thread_handle);
702 public bool Join(TimeSpan timeout)
704 // LAMESPEC: says to throw ArgumentException too
705 int ms=Convert.ToInt32(timeout.TotalMilliseconds);
707 if(ms < 0 || ms > Int32.MaxValue) {
708 throw new ArgumentOutOfRangeException("timeout out of range");
710 return Join_internal(ms, system_thread_handle);
714 [MethodImplAttribute(MethodImplOptions.InternalCall)]
715 public extern static void MemoryBarrier ();
717 [MethodImplAttribute(MethodImplOptions.InternalCall)]
718 private extern void Resume_internal();
723 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
724 public void Resume ()
729 [MethodImplAttribute (MethodImplOptions.InternalCall)]
730 private extern static void SpinWait_nop ();
734 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
736 public static void SpinWait (int iterations)
740 while (iterations-- > 0)
747 private void StartSafe ()
750 if (threadstart is ThreadStart) {
751 ((ThreadStart) threadstart) ();
753 ((ParameterizedThreadStart) threadstart) (start_obj);
755 } catch (Exception ex) {
756 MoonlightUnhandledException (ex);
760 static MethodInfo moonlight_unhandled_exception = null;
762 static internal void MoonlightUnhandledException (Exception e)
765 if (moonlight_unhandled_exception == null) {
766 var assembly = System.Reflection.Assembly.Load ("System.Windows, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e");
767 var application = assembly.GetType ("System.Windows.Application");
768 moonlight_unhandled_exception = application.GetMethod ("OnUnhandledException",
769 System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
771 moonlight_unhandled_exception.Invoke (null, new object [] { null, e });
775 Console.WriteLine ("Unexpected exception while trying to report unhandled application exception: {0}", e);
782 public void Start() {
783 // propagate informations from the original thread to the new thread
785 if (!ExecutionContext.IsFlowSuppressed ())
786 ec_to_set = ExecutionContext.Capture ();
788 // before 2.0 this was only used for security (mostly CAS) so we
789 // do this only if the security manager is active
790 if (SecurityManager.SecurityEnabled)
791 ec_to_set = ExecutionContext.Capture ();
793 if (CurrentThread._principal != null)
794 _principal = CurrentThread._principal;
796 // Thread_internal creates and starts the new thread,
798 if (Thread_internal((ThreadStart) StartSafe) == (IntPtr) 0)
800 if (Thread_internal(threadstart) == (IntPtr) 0)
802 throw new SystemException ("Thread creation failed.");
805 [MethodImplAttribute(MethodImplOptions.InternalCall)]
806 private extern void Suspend_internal();
811 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
812 public void Suspend ()
817 // Closes the system thread handle
818 [MethodImplAttribute(MethodImplOptions.InternalCall)]
819 private extern void Thread_free_internal(IntPtr handle);
822 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
825 // Free up the handle
826 if (system_thread_handle != (IntPtr) 0)
827 Thread_free_internal(system_thread_handle);
830 [MethodImplAttribute (MethodImplOptions.InternalCall)]
831 extern private void SetState (ThreadState set);
833 [MethodImplAttribute (MethodImplOptions.InternalCall)]
834 extern private void ClrState (ThreadState clr);
836 [MethodImplAttribute (MethodImplOptions.InternalCall)]
837 extern private ThreadState GetState ();
841 [MethodImplAttribute (MethodImplOptions.InternalCall)]
842 extern public static byte VolatileRead (ref byte address);
844 [MethodImplAttribute (MethodImplOptions.InternalCall)]
845 extern public static double VolatileRead (ref double address);
847 [MethodImplAttribute (MethodImplOptions.InternalCall)]
848 extern public static short VolatileRead (ref short address);
850 [MethodImplAttribute (MethodImplOptions.InternalCall)]
851 extern public static int VolatileRead (ref int address);
853 [MethodImplAttribute (MethodImplOptions.InternalCall)]
854 extern public static long VolatileRead (ref long address);
856 [MethodImplAttribute (MethodImplOptions.InternalCall)]
857 extern public static IntPtr VolatileRead (ref IntPtr address);
859 [MethodImplAttribute (MethodImplOptions.InternalCall)]
860 extern public static object VolatileRead (ref object address);
862 [CLSCompliant(false)]
863 [MethodImplAttribute (MethodImplOptions.InternalCall)]
864 extern public static sbyte VolatileRead (ref sbyte address);
866 [MethodImplAttribute (MethodImplOptions.InternalCall)]
867 extern public static float VolatileRead (ref float address);
869 [CLSCompliant (false)]
870 [MethodImplAttribute (MethodImplOptions.InternalCall)]
871 extern public static ushort VolatileRead (ref ushort address);
873 [CLSCompliant (false)]
874 [MethodImplAttribute (MethodImplOptions.InternalCall)]
875 extern public static uint VolatileRead (ref uint address);
877 [CLSCompliant (false)]
878 [MethodImplAttribute (MethodImplOptions.InternalCall)]
879 extern public static ulong VolatileRead (ref ulong address);
881 [CLSCompliant (false)]
882 [MethodImplAttribute (MethodImplOptions.InternalCall)]
883 extern public static UIntPtr VolatileRead (ref UIntPtr address);
885 [MethodImplAttribute (MethodImplOptions.InternalCall)]
886 extern public static void VolatileWrite (ref byte address, byte value);
888 [MethodImplAttribute (MethodImplOptions.InternalCall)]
889 extern public static void VolatileWrite (ref double address, double value);
891 [MethodImplAttribute (MethodImplOptions.InternalCall)]
892 extern public static void VolatileWrite (ref short address, short value);
894 [MethodImplAttribute (MethodImplOptions.InternalCall)]
895 extern public static void VolatileWrite (ref int address, int value);
897 [MethodImplAttribute (MethodImplOptions.InternalCall)]
898 extern public static void VolatileWrite (ref long address, long value);
900 [MethodImplAttribute (MethodImplOptions.InternalCall)]
901 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
903 [MethodImplAttribute (MethodImplOptions.InternalCall)]
904 extern public static void VolatileWrite (ref object address, object value);
906 [CLSCompliant(false)]
907 [MethodImplAttribute (MethodImplOptions.InternalCall)]
908 extern public static void VolatileWrite (ref sbyte address, sbyte value);
910 [MethodImplAttribute (MethodImplOptions.InternalCall)]
911 extern public static void VolatileWrite (ref float address, float value);
913 [CLSCompliant (false)]
914 [MethodImplAttribute (MethodImplOptions.InternalCall)]
915 extern public static void VolatileWrite (ref ushort address, ushort value);
917 [CLSCompliant (false)]
918 [MethodImplAttribute (MethodImplOptions.InternalCall)]
919 extern public static void VolatileWrite (ref uint address, uint value);
921 [CLSCompliant (false)]
922 [MethodImplAttribute (MethodImplOptions.InternalCall)]
923 extern public static void VolatileWrite (ref ulong address, ulong value);
925 [CLSCompliant (false)]
926 [MethodImplAttribute (MethodImplOptions.InternalCall)]
927 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
932 private static int GetNewManagedId() {
933 return Interlocked.Increment(ref _managed_id_counter);
936 public Thread (ThreadStart start, int maxStackSize)
939 throw new ArgumentNullException ("start");
940 if (maxStackSize < 131072)
941 throw new ArgumentException ("< 128 kb", "maxStackSize");
944 stack_size = maxStackSize;
948 public Thread (ParameterizedThreadStart start)
951 throw new ArgumentNullException ("start");
957 public Thread (ParameterizedThreadStart start, int maxStackSize)
960 throw new ArgumentNullException ("start");
961 if (maxStackSize < 131072)
962 throw new ArgumentException ("< 128 kb", "maxStackSize");
965 stack_size = maxStackSize;
969 [MonoTODO ("limited to CompressedStack support")]
970 public ExecutionContext ExecutionContext {
971 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
974 _ec = new ExecutionContext ();
979 public int ManagedThreadId {
980 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
982 if (managed_id == 0) {
983 int new_managed_id = GetNewManagedId ();
985 Interlocked.CompareExchange (ref managed_id, new_managed_id, 0);
992 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
993 public static void BeginCriticalRegion ()
995 CurrentThread.critical_region_level++;
998 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
999 public static void EndCriticalRegion ()
1001 CurrentThread.critical_region_level--;
1004 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1005 public static void BeginThreadAffinity ()
1007 // Managed and native threads are currently bound together.
1010 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
1011 public static void EndThreadAffinity ()
1013 // Managed and native threads are currently bound together.
1016 public ApartmentState GetApartmentState ()
1018 return (ApartmentState)apartment_state;
1021 public void SetApartmentState (ApartmentState state)
1023 if (!TrySetApartmentState (state))
1024 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
1027 public bool TrySetApartmentState (ApartmentState state)
1029 /* Only throw this exception when changing the
1030 * state of another thread. See bug 324338
1032 if ((this != CurrentThread) &&
1033 (ThreadState & ThreadState.Unstarted) == 0)
1034 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
1036 if ((ApartmentState)apartment_state != ApartmentState.Unknown)
1039 apartment_state = (byte)state;
1044 [ComVisible (false)]
1045 public override int GetHashCode ()
1047 return ManagedThreadId;
1050 public void Start (object parameter)
1052 start_obj = parameter;
1056 internal ExecutionContext ExecutionContext {
1059 _ec = new ExecutionContext ();
1065 // NOTE: This method doesn't show in the class library status page because
1066 // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
1068 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
1069 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
1071 [Obsolete ("see CompressedStack class")]
1078 CompressedStack GetCompressedStack ()
1080 // Note: returns null if no CompressedStack has been set.
1081 // However CompressedStack.GetCompressedStack returns an
1082 // (empty?) CompressedStack instance.
1083 CompressedStack cs = ExecutionContext.SecurityContext.CompressedStack;
1084 return ((cs == null) || cs.IsEmpty ()) ? null : cs.CreateCopy ();
1087 // NOTE: This method doesn't show in the class library status page because
1088 // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
1090 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
1091 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
1093 [Obsolete ("see CompressedStack class")]
1100 void SetCompressedStack (CompressedStack stack)
1102 ExecutionContext.SecurityContext.CompressedStack = stack;
1106 void _Thread.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1108 throw new NotImplementedException ();
1111 void _Thread.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1113 throw new NotImplementedException ();
1116 void _Thread.GetTypeInfoCount (out uint pcTInfo)
1118 throw new NotImplementedException ();
1121 void _Thread.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
1122 IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1124 throw new NotImplementedException ();