[corlib] Re-introduce Thread.Abort/Suspend/Resume, but make them throw NotSupportedEx...
[mono.git] / mcs / class / corlib / System.Threading / Thread.cs
1 //
2 // System.Threading.Thread.cs
3 //
4 // Author:
5 //   Dick Porter (dick@ximian.com)
6 //
7 // (C) Ximian, Inc.  http://www.ximian.com
8 // Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
9 //
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:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
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.
28 //
29
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;
38 using System.IO;
39 using System.Collections.Generic;
40 using System.Reflection;
41 using System.Security;
42 using System.Diagnostics;
43 using System.Runtime.ConstrainedExecution;
44
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
50                 int lock_thread_id;
51                 // stores a thread handle
52                 internal IntPtr system_thread_handle;
53
54                 /* Note this is an opaque object (an array), not a CultureInfo */
55                 private object cached_culture_info;
56                 /* accessed only from unmanaged code */
57                 private IntPtr name;
58                 private int name_len; 
59                 private ThreadState state;
60                 private object abort_exc;
61                 private int abort_state_handle;
62                 /* thread_id is only accessed from unmanaged code */
63                 internal Int64 thread_id;
64                 
65                 /* start_notify is used by the runtime to signal that Start()
66                  * is ok to return
67                  */
68                 private IntPtr start_notify;
69                 private IntPtr stack_ptr;
70                 private UIntPtr static_data; /* GC-tracked */
71                 private IntPtr runtime_thread_info;
72                 /* current System.Runtime.Remoting.Contexts.Context instance
73                    keep as an object to avoid triggering its class constructor when not needed */
74                 private object current_appcontext;
75                 private object pending_exception;
76                 private object root_domain_thread;
77                 internal byte[] _serialized_principal;
78                 internal int _serialized_principal_version;
79                 private IntPtr appdomain_refs;
80                 private int interruption_requested;
81                 private IntPtr synch_cs;
82                 internal bool threadpool_thread;
83                 private bool thread_interrupt_requested;
84                 /* These are used from managed code */
85                 internal int stack_size;
86                 internal byte apartment_state;
87                 internal volatile int critical_region_level;
88                 internal int managed_id;
89                 private int small_id;
90                 private IntPtr manage_callback;
91                 private IntPtr interrupt_on_stop;
92                 private IntPtr flags;
93                 private IntPtr thread_pinning_ref;
94                 /* 
95                  * These fields are used to avoid having to increment corlib versions
96                  * when a new field is added to the unmanaged MonoThread structure.
97                  */
98                 private IntPtr unused1;
99                 private IntPtr unused2;
100                 #endregion
101 #pragma warning restore 169, 414, 649
102
103                 // Closes the system thread handle
104                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
105                 private extern void Thread_free_internal(IntPtr handle);
106
107                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
108                 ~InternalThread() {
109                         Thread_free_internal(system_thread_handle);
110                 }
111         }
112
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;
119                 #endregion
120 #pragma warning restore 414
121
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;
128
129                 // the name of current_thread is
130                 // important because they are used by the runtime.
131
132                 [ThreadStatic]
133                 static Thread current_thread;
134
135                 static internal CultureInfo default_culture;
136                 static internal CultureInfo default_ui_culture;
137
138                 // can be both a ThreadStart and a ParameterizedThreadStart
139                 private MulticastDelegate m_Delegate;
140
141                 private ExecutionContext m_ExecutionContext;    // this call context follows the logical thread
142
143                 private bool m_ExecutionContextBelongsToOuterScope;
144
145                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
146                 private extern void ConstructInternalThread ();
147
148                 private InternalThread Internal {
149                         get {
150                                 if (internal_thread == null)
151                                         ConstructInternalThread ();
152                                 return internal_thread;
153                         }
154                 }
155
156                 public static Context CurrentContext {
157                         [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
158                         get {
159                                 return(AppDomain.InternalGetContext ());
160                         }
161                 }
162
163                 /*
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.
168                  */
169                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
170                 private extern static byte[] ByteArrayToRootDomain (byte[] arr);
171
172                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
173                 private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
174
175                 static void DeserializePrincipal (Thread th)
176                 {
177                         MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
178                         int type = ms.ReadByte ();
179                         if (type == 0) {
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;
189                                 if (n_roles >= 0) {
190                                         roles = new string [n_roles];
191                                         for (int i = 0; i < n_roles; i++)
192                                                 roles [i] = reader.ReadString ();
193                                 }
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);
198                         }
199                 }
200
201                 static void SerializePrincipal (Thread th, IPrincipal value)
202                 {
203                         MemoryStream ms = new MemoryStream ();
204                         bool done = false;
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) {
211                                                         ms.WriteByte (2);
212                                                         done = true;
213                                                 } else if (gp.Roles.Length == 0) {
214                                                         ms.WriteByte (3);
215                                                         done = true;
216                                                 }
217                                         } else {
218                                                 ms.WriteByte (1);
219                                                 BinaryWriter br = new BinaryWriter (ms);
220                                                 br.Write (gp.Identity.Name);
221                                                 br.Write (gp.Identity.AuthenticationType);
222                                                 string [] roles = gp.Roles;
223                                                 if  (roles == null) {
224                                                         br.Write ((int) (-1));
225                                                 } else {
226                                                         br.Write (roles.Length);
227                                                         foreach (string s in roles) {
228                                                                 br.Write (s);
229                                                         }
230                                                 }
231                                                 br.Flush ();
232                                                 done = true;
233                                         }
234                                 }
235                         }
236                         if (!done) {
237                                 ms.WriteByte (0);
238                                 BinaryFormatter bf = new BinaryFormatter ();
239                                 try {
240                                         bf.Serialize (ms, value);
241                                 } catch {}
242                         }
243                         th.Internal._serialized_principal = ByteArrayToRootDomain (ms.ToArray ());
244                 }
245
246                 public static IPrincipal CurrentPrincipal {
247                         get {
248                                 Thread th = CurrentThread;
249
250                                 if (th.principal_version != th.Internal._serialized_principal_version)
251                                         th.principal = null;
252
253                                 if (th.principal != null)
254                                         return th.principal;
255
256                                 if (th.Internal._serialized_principal != null) {
257                                         try {
258                                                 DeserializePrincipal (th);
259                                                 return th.principal;
260                                         } catch {}
261                                 }
262
263                                 th.principal = GetDomain ().DefaultPrincipal;
264                                 th.principal_version = th.Internal._serialized_principal_version;
265                                 return th.principal;
266                         }
267                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
268                         set {
269                                 Thread th = CurrentThread;
270
271                                 if (value != GetDomain ().DefaultPrincipal) {
272                                         ++th.Internal._serialized_principal_version;
273                                         try {
274                                                 SerializePrincipal (th, value);
275                                         } catch (Exception) {
276                                                 th.Internal._serialized_principal = null;
277                                         }
278                                         th.principal_version = th.Internal._serialized_principal_version;
279                                 } else {
280                                         th.Internal._serialized_principal = null;
281                                 }
282
283                                 th.principal = value;
284                         }
285                 }
286
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();
291
292                 public static Thread CurrentThread {
293                         [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
294                         get {
295                                 if (current_thread == null)
296                                         current_thread = new Thread (CurrentInternalThread_internal ());
297                                 return current_thread;
298                         }
299                 }
300
301                 internal static int CurrentThreadId {
302                         get {
303                                 return (int)(CurrentThread.internal_thread.thread_id);
304                         }
305                 }
306
307                 public static AppDomain GetDomain() {
308                         return AppDomain.CurrentDomain;
309                 }
310
311                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
312                 public extern static int GetDomainID();
313
314                 // Returns the system thread handle
315                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
316                 private extern IntPtr Thread_internal (MulticastDelegate start);
317
318                 private Thread (InternalThread it) {
319                         internal_thread = it;
320                 }
321                 
322                 // part of ".NETPortable,Version=v4.0,Profile=Profile3" i.e. FX4 and SL4
323                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
324                 ~Thread ()
325                 {
326                 }
327
328                 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
329                 public ApartmentState ApartmentState {
330                         get {
331                                 if ((ThreadState & ThreadState.Stopped) != 0)
332                                         throw new ThreadStateException ("Thread is dead; state can not be accessed.");
333
334                                 return (ApartmentState)Internal.apartment_state;
335                         }
336
337                         set {
338                                 TrySetApartmentState (value);
339                         }
340                 }
341
342                 //[MethodImplAttribute (MethodImplOptions.InternalCall)]
343                 //private static extern int current_lcid ();
344
345                 public CultureInfo CurrentCulture {
346                         get {
347                                 CultureInfo culture = current_culture;
348                                 if (current_culture_set && culture != null)
349                                         return culture;
350
351                                 if (default_culture != null)
352                                         return default_culture;
353
354                                 current_culture = culture = CultureInfo.ConstructCurrentCulture ();
355                                 return culture;
356                         }
357                         
358                         [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
359                         set {
360                                 if (value == null)
361                                         throw new ArgumentNullException ("value");
362
363                                 value.CheckNeutral ();
364                                 current_culture = value;
365                                 current_culture_set = true;
366                         }
367                 }
368
369                 public CultureInfo CurrentUICulture {
370                         get {
371                                 CultureInfo culture = current_ui_culture;
372                                 if (current_ui_culture_set && culture != null)
373                                         return culture;
374
375                                 if (default_ui_culture != null)
376                                         return default_ui_culture;
377
378                                 current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
379                                 return culture;
380                         }
381                         
382                         set {
383                                 if (value == null)
384                                         throw new ArgumentNullException ("value");
385                                 current_ui_culture = value;
386                                 current_ui_culture_set = true;
387                         }
388                 }
389
390                 public bool IsThreadPoolThread {
391                         get {
392                                 return IsThreadPoolThreadInternal;
393                         }
394                 }
395
396                 internal bool IsThreadPoolThreadInternal {
397                         get {
398                                 return Internal.threadpool_thread;
399                         }
400                         set {
401                                 Internal.threadpool_thread = value;
402                         }
403                 }
404
405                 public bool IsAlive {
406                         get {
407                                 ThreadState curstate = GetState (Internal);
408                                 
409                                 if((curstate & ThreadState.Aborted) != 0 ||
410                                    (curstate & ThreadState.Stopped) != 0 ||
411                                    (curstate & ThreadState.Unstarted) != 0) {
412                                         return(false);
413                                 } else {
414                                         return(true);
415                                 }
416                         }
417                 }
418
419                 public bool IsBackground {
420                         get {
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.");
424
425                                 return (thread_state & ThreadState.Background) != 0;
426                         }
427                         
428                         set {
429                                 if (value) {
430                                         SetState (Internal, ThreadState.Background);
431                                 } else {
432                                         ClrState (Internal, ThreadState.Background);
433                                 }
434                         }
435                 }
436
437                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
438                 private extern static string GetName_internal (InternalThread thread);
439
440                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
441                 private extern static void SetName_internal (InternalThread thread, String name);
442
443                 /* 
444                  * The thread name must be shared by appdomains, so it is stored in
445                  * unmanaged code.
446                  */
447
448                 public string Name {
449                         get {
450                                 return GetName_internal (Internal);
451                         }
452                         
453                         set {
454                                 SetName_internal (Internal, value);
455                         }
456                 }
457
458                 public ThreadState ThreadState {
459                         get {
460                                 return GetState (Internal);
461                         }
462                 }
463
464 #if MONO_FEATURE_THREAD_ABORT
465                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
466                 private extern static void Abort_internal (InternalThread thread, object stateInfo);
467
468                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
469                 public void Abort () 
470                 {
471                         Abort_internal (Internal, null);
472                 }
473
474                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
475                 public void Abort (object stateInfo) 
476                 {
477                         Abort_internal (Internal, stateInfo);
478                 }
479
480                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
481                 extern object GetAbortExceptionState ();
482
483                 internal object AbortReason {
484                         get {
485                                 return GetAbortExceptionState ();
486                         }
487                 }
488
489                 void ClearAbortReason ()
490                 {
491                 }
492 #else
493                 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
494                 public void Abort ()
495                 {
496                         throw new NotSupportedException ("Thread.Abort is not supported on the current platform.");
497                 }
498
499                 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
500                 public void Abort (object stateInfo)
501                 {
502                         throw new NotSupportedException ("Thread.Abort is not supported on the current platform.");
503                 }
504
505                 [Obsolete ("Thread.ResetAbort is not supported on the current platform.", true)]
506                 public static void ResetAbort ()
507                 {
508                         throw new NotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
509                 }
510 #endif // MONO_FEATURE_THREAD_ABORT
511
512                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
513                 private extern static void SpinWait_nop ();
514
515
516                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
517                 public static void SpinWait (int iterations) 
518                 {
519                         if (iterations < 0)
520                                 return;
521                         while (iterations-- > 0)
522                         {
523                                 SpinWait_nop ();
524                         }
525                 }
526
527                 void StartInternal (IPrincipal principal, ref StackCrawlMark stackMark)
528                 {
529 #if FEATURE_ROLE_BASED_SECURITY
530                         Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
531 #endif
532
533                         // Thread_internal creates and starts the new thread, 
534                         if (Thread_internal(m_Delegate) == IntPtr.Zero)
535                                 throw new SystemException ("Thread creation failed.");
536
537                         m_ThreadStartArg = null;
538                 }
539
540                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
541                 extern private static void SetState (InternalThread thread, ThreadState set);
542
543                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
544                 extern private static void ClrState (InternalThread thread, ThreadState clr);
545
546                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
547                 extern private static ThreadState GetState (InternalThread thread);
548
549                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
550                 extern public static byte VolatileRead (ref byte address);
551                 
552                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
553                 extern public static double VolatileRead (ref double address);
554                 
555                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
556                 extern public static short VolatileRead (ref short address);
557                 
558                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
559                 extern public static int VolatileRead (ref int address);
560                 
561                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
562                 extern public static long VolatileRead (ref long address);
563                 
564                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
565                 extern public static IntPtr VolatileRead (ref IntPtr address);
566                 
567                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
568                 extern public static object VolatileRead (ref object address);
569
570                 [CLSCompliant(false)]
571                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
572                 extern public static sbyte VolatileRead (ref sbyte address);
573                 
574                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
575                 extern public static float VolatileRead (ref float address);
576
577                 [CLSCompliant (false)]
578                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
579                 extern public static ushort VolatileRead (ref ushort address);
580
581                 [CLSCompliant (false)]
582                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
583                 extern public static uint VolatileRead (ref uint address);
584
585                 [CLSCompliant (false)]
586                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
587                 extern public static ulong VolatileRead (ref ulong address);
588
589                 [CLSCompliant (false)]
590                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
591                 extern public static UIntPtr VolatileRead (ref UIntPtr address);
592
593                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
594                 extern public static void VolatileWrite (ref byte address, byte value);
595                 
596                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
597                 extern public static void VolatileWrite (ref double address, double value);
598                 
599                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
600                 extern public static void VolatileWrite (ref short address, short value);
601                 
602                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
603                 extern public static void VolatileWrite (ref int address, int value);
604                 
605                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
606                 extern public static void VolatileWrite (ref long address, long value);
607                 
608                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
609                 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
610                 
611                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
612                 extern public static void VolatileWrite (ref object address, object value);
613
614                 [CLSCompliant(false)]
615                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
616                 extern public static void VolatileWrite (ref sbyte address, sbyte value);
617                 
618                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
619                 extern public static void VolatileWrite (ref float address, float value);
620
621                 [CLSCompliant (false)]
622                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
623                 extern public static void VolatileWrite (ref ushort address, ushort value);
624
625                 [CLSCompliant (false)]
626                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
627                 extern public static void VolatileWrite (ref uint address, uint value);
628
629                 [CLSCompliant (false)]
630                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
631                 extern public static void VolatileWrite (ref ulong address, ulong value);
632
633                 [CLSCompliant (false)]
634                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
635                 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
636                 
637                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
638                 extern static int SystemMaxStackStize ();
639
640                 static int GetProcessDefaultStackSize (int maxStackSize)
641                 {
642                         if (maxStackSize == 0)
643                                 return 0;
644
645                         if (maxStackSize < 131072) // make sure stack is at least 128k big
646                                 return 131072;
647
648                         int page_size = Environment.GetPageSize ();
649
650                         if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
651                                 maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
652
653                         /* Respect the max stack size imposed by the system*/
654                         return Math.Min (maxStackSize, SystemMaxStackStize ());
655                 }
656
657                 void SetStart (MulticastDelegate start, int maxStackSize)
658                 {
659                         m_Delegate = start;
660                         Internal.stack_size = maxStackSize;
661                 }
662
663                 public int ManagedThreadId {
664                         [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
665                         get {
666                                 return Internal.managed_id;
667                         }
668                 }
669
670                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
671                 public static void BeginCriticalRegion ()
672                 {
673                         CurrentThread.Internal.critical_region_level++;
674                 }
675
676                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
677                 public static void EndCriticalRegion ()
678                 {
679                         CurrentThread.Internal.critical_region_level--;
680                 }
681
682                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
683                 public static void BeginThreadAffinity ()
684                 {
685                         // Managed and native threads are currently bound together.
686                 }
687
688                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
689                 public static void EndThreadAffinity ()
690                 {
691                         // Managed and native threads are currently bound together.
692                 }
693
694                 public ApartmentState GetApartmentState ()
695                 {
696                         return (ApartmentState)Internal.apartment_state;
697                 }
698
699                 public void SetApartmentState (ApartmentState state)
700                 {
701                         if (!TrySetApartmentState (state))
702                                 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
703                 }
704
705                 public bool TrySetApartmentState (ApartmentState state) 
706                 {
707                         if ((ThreadState & ThreadState.Unstarted) == 0)
708                                 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
709
710                         if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown && 
711                             (ApartmentState)Internal.apartment_state != state)
712                                 return false;
713
714                         Internal.apartment_state = (byte)state;
715
716                         return true;
717                 }
718                 
719                 [ComVisible (false)]
720                 public override int GetHashCode ()
721                 {
722                         return ManagedThreadId;
723                 }
724
725                 internal CultureInfo GetCurrentUICultureNoAppX ()
726                 {
727                         return CultureInfo.CurrentUICulture;
728                 }
729
730                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
731                 internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
732
733                 // This is a mono extension to gather the stack traces for all running threads
734                 internal static Dictionary<Thread, StackTrace> Mono_GetStackTraces () {
735                         Thread[] threads;
736                         object[] stack_frames;
737
738                         GetStackTraces (out threads, out stack_frames);
739
740                         var res = new Dictionary<Thread, StackTrace> ();
741                         for (int i = 0; i < threads.Length; ++i)
742                                 res [threads [i]] = new StackTrace ((StackFrame[])stack_frames [i]);
743                         return res;
744                 }
745
746 #if !MONO_FEATURE_THREAD_SUSPEND_RESUME
747                 [Obsolete ("Thread.Suspend is not supported on the current platform.", true)]
748                 public void Suspend ()
749                 {
750                         throw new NotSupportedException ("Thread.Suspend is not supported on the current platform.");
751                 }
752
753                 [Obsolete ("Thread.Resume is not supported on the current platform.", true)]
754                 public void Resume ()
755                 {
756                         throw new NotSupportedException ("Thread.Resume is not supported on the current platform.");
757                 }
758 #endif
759         }
760 }