26222aca533fc40cfcf949e47a8cdb0b9cd800c7
[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                 IntPtr handle;
53                 IntPtr native_handle; // used only on Win32
54
55                 /* Note this is an opaque object (an array), not a CultureInfo */
56                 private object cached_culture_info;
57                 /* accessed only from unmanaged code */
58                 private IntPtr name;
59                 private int name_len; 
60                 private ThreadState state;
61                 private object abort_exc;
62                 private int abort_state_handle;
63                 /* thread_id is only accessed from unmanaged code */
64                 internal Int64 thread_id;
65                 private IntPtr stack_ptr;
66                 private UIntPtr static_data; /* GC-tracked */
67                 private IntPtr runtime_thread_info;
68                 /* current System.Runtime.Remoting.Contexts.Context instance
69                    keep as an object to avoid triggering its class constructor when not needed */
70                 private object current_appcontext;
71                 private object root_domain_thread;
72                 internal byte[] _serialized_principal;
73                 internal int _serialized_principal_version;
74                 private IntPtr appdomain_refs;
75                 private int interruption_requested;
76                 private IntPtr synch_cs;
77                 internal bool threadpool_thread;
78                 private bool thread_interrupt_requested;
79                 /* These are used from managed code */
80                 internal int stack_size;
81                 internal byte apartment_state;
82                 internal volatile int critical_region_level;
83                 internal int managed_id;
84                 private int small_id;
85                 private IntPtr manage_callback;
86                 private IntPtr interrupt_on_stop;
87                 private IntPtr flags;
88                 private IntPtr thread_pinning_ref;
89                 private IntPtr abort_protected_block_count;
90                 private int priority = (int) ThreadPriority.Normal;
91                 private IntPtr owned_mutex;
92                 private IntPtr suspended_event;
93                 private int self_suspended;
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
101                 /* This is used only to check that we are in sync between the representation
102                  * of MonoInternalThread in native and InternalThread in managed
103                  *
104                  * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */
105                 private IntPtr last;
106                 #endregion
107 #pragma warning restore 169, 414, 649
108
109                 // Closes the system thread handle
110                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
111                 private extern void Thread_free_internal();
112
113                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
114                 ~InternalThread() {
115                         Thread_free_internal();
116                 }
117         }
118
119         [StructLayout (LayoutKind.Sequential)]
120         public sealed partial class Thread {
121 #pragma warning disable 414             
122                 #region Sync with metadata/object-internals.h
123                 private InternalThread internal_thread;
124                 object m_ThreadStartArg;
125                 object pending_exception;
126                 #endregion
127 #pragma warning restore 414
128
129                 IPrincipal principal;
130                 int principal_version;
131
132                 // the name of current_thread is
133                 // important because they are used by the runtime.
134
135                 [ThreadStatic]
136                 static Thread current_thread;
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                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
288                 private extern static Thread GetCurrentThread ();
289
290                 public static Thread CurrentThread {
291                         [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
292                         get {
293                                 Thread current = current_thread;
294                                 if (current != null)
295                                         return current;
296                                 // This will set the current_thread tls variable
297                                 return GetCurrentThread ();
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                 public bool IsThreadPoolThread {
343                         get {
344                                 return IsThreadPoolThreadInternal;
345                         }
346                 }
347
348                 internal bool IsThreadPoolThreadInternal {
349                         get {
350                                 return Internal.threadpool_thread;
351                         }
352                         set {
353                                 Internal.threadpool_thread = value;
354                         }
355                 }
356
357                 public bool IsAlive {
358                         get {
359                                 ThreadState curstate = GetState (Internal);
360                                 
361                                 if((curstate & ThreadState.Aborted) != 0 ||
362                                    (curstate & ThreadState.Stopped) != 0 ||
363                                    (curstate & ThreadState.Unstarted) != 0) {
364                                         return(false);
365                                 } else {
366                                         return(true);
367                                 }
368                         }
369                 }
370
371                 public bool IsBackground {
372                         get {
373                                 ThreadState thread_state = GetState (Internal);
374                                 if ((thread_state & ThreadState.Stopped) != 0)
375                                         throw new ThreadStateException ("Thread is dead; state can not be accessed.");
376
377                                 return (thread_state & ThreadState.Background) != 0;
378                         }
379                         
380                         set {
381                                 if (value) {
382                                         SetState (Internal, ThreadState.Background);
383                                 } else {
384                                         ClrState (Internal, ThreadState.Background);
385                                 }
386                         }
387                 }
388
389                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
390                 private extern static string GetName_internal (InternalThread thread);
391
392                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
393                 private extern static void SetName_internal (InternalThread thread, String name);
394
395                 /* 
396                  * The thread name must be shared by appdomains, so it is stored in
397                  * unmanaged code.
398                  */
399
400                 public string Name {
401                         get {
402                                 return GetName_internal (Internal);
403                         }
404                         
405                         set {
406                                 SetName_internal (Internal, value);
407                         }
408                 }
409
410                 public ThreadState ThreadState {
411                         get {
412                                 return GetState (Internal);
413                         }
414                 }
415
416 #if MONO_FEATURE_THREAD_ABORT
417                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
418                 private extern static void Abort_internal (InternalThread thread, object stateInfo);
419
420                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
421                 public void Abort () 
422                 {
423                         Abort_internal (Internal, null);
424                 }
425
426                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
427                 public void Abort (object stateInfo) 
428                 {
429                         Abort_internal (Internal, stateInfo);
430                 }
431
432                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
433                 extern object GetAbortExceptionState ();
434
435                 internal object AbortReason {
436                         get {
437                                 return GetAbortExceptionState ();
438                         }
439                 }
440
441                 void ClearAbortReason ()
442                 {
443                 }
444 #else
445                 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
446                 public void Abort ()
447                 {
448                         throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
449                 }
450
451                 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
452                 public void Abort (object stateInfo)
453                 {
454                         throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
455                 }
456
457                 [Obsolete ("Thread.ResetAbort is not supported on the current platform.", true)]
458                 public static void ResetAbort ()
459                 {
460                         throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
461                 }
462
463                 internal object AbortReason {
464                         get {
465                                 throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
466                         }
467                 }
468 #endif // MONO_FEATURE_THREAD_ABORT
469
470                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
471                 private extern static void SpinWait_nop ();
472
473
474                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
475                 public static void SpinWait (int iterations) 
476                 {
477                         if (iterations < 0)
478                                 return;
479                         while (iterations-- > 0)
480                         {
481                                 SpinWait_nop ();
482                         }
483                 }
484
485                 void StartInternal (IPrincipal principal, ref StackCrawlMark stackMark)
486                 {
487 #if FEATURE_ROLE_BASED_SECURITY
488                         Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
489 #endif
490
491                         // Thread_internal creates and starts the new thread, 
492                         if (Thread_internal(m_Delegate) == IntPtr.Zero)
493                                 throw new SystemException ("Thread creation failed.");
494
495                         m_ThreadStartArg = null;
496                 }
497
498                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
499                 extern private static void SetState (InternalThread thread, ThreadState set);
500
501                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
502                 extern private static void ClrState (InternalThread thread, ThreadState clr);
503
504                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
505                 extern private static ThreadState GetState (InternalThread thread);
506
507                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
508                 extern public static byte VolatileRead (ref byte address);
509                 
510                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
511                 extern public static double VolatileRead (ref double address);
512                 
513                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
514                 extern public static short VolatileRead (ref short address);
515                 
516                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
517                 extern public static int VolatileRead (ref int address);
518                 
519                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
520                 extern public static long VolatileRead (ref long address);
521                 
522                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
523                 extern public static IntPtr VolatileRead (ref IntPtr address);
524                 
525                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
526                 extern public static object VolatileRead (ref object address);
527
528                 [CLSCompliant(false)]
529                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
530                 extern public static sbyte VolatileRead (ref sbyte address);
531                 
532                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
533                 extern public static float VolatileRead (ref float address);
534
535                 [CLSCompliant (false)]
536                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
537                 extern public static ushort VolatileRead (ref ushort address);
538
539                 [CLSCompliant (false)]
540                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
541                 extern public static uint VolatileRead (ref uint address);
542
543                 [CLSCompliant (false)]
544                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
545                 extern public static ulong VolatileRead (ref ulong address);
546
547                 [CLSCompliant (false)]
548                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
549                 extern public static UIntPtr VolatileRead (ref UIntPtr address);
550
551                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
552                 extern public static void VolatileWrite (ref byte address, byte value);
553                 
554                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
555                 extern public static void VolatileWrite (ref double address, double value);
556                 
557                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
558                 extern public static void VolatileWrite (ref short address, short value);
559                 
560                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
561                 extern public static void VolatileWrite (ref int address, int value);
562                 
563                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
564                 extern public static void VolatileWrite (ref long address, long value);
565                 
566                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
567                 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
568                 
569                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
570                 extern public static void VolatileWrite (ref object address, object value);
571
572                 [CLSCompliant(false)]
573                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
574                 extern public static void VolatileWrite (ref sbyte address, sbyte value);
575                 
576                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
577                 extern public static void VolatileWrite (ref float address, float value);
578
579                 [CLSCompliant (false)]
580                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
581                 extern public static void VolatileWrite (ref ushort address, ushort value);
582
583                 [CLSCompliant (false)]
584                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
585                 extern public static void VolatileWrite (ref uint address, uint value);
586
587                 [CLSCompliant (false)]
588                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
589                 extern public static void VolatileWrite (ref ulong address, ulong value);
590
591                 [CLSCompliant (false)]
592                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
593                 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
594                 
595                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
596                 extern static int SystemMaxStackStize ();
597
598                 static int GetProcessDefaultStackSize (int maxStackSize)
599                 {
600                         if (maxStackSize == 0)
601                                 return 0;
602
603                         if (maxStackSize < 131072) // make sure stack is at least 128k big
604                                 return 131072;
605
606                         int page_size = Environment.GetPageSize ();
607
608                         if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
609                                 maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
610
611                         /* Respect the max stack size imposed by the system*/
612                         return Math.Min (maxStackSize, SystemMaxStackStize ());
613                 }
614
615                 void SetStart (MulticastDelegate start, int maxStackSize)
616                 {
617                         m_Delegate = start;
618                         Internal.stack_size = maxStackSize;
619                 }
620
621                 public int ManagedThreadId {
622                         [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
623                         get {
624                                 return Internal.managed_id;
625                         }
626                 }
627
628                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
629                 public static void BeginCriticalRegion ()
630                 {
631                         CurrentThread.Internal.critical_region_level++;
632                 }
633
634                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
635                 public static void EndCriticalRegion ()
636                 {
637                         CurrentThread.Internal.critical_region_level--;
638                 }
639
640                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
641                 public static void BeginThreadAffinity ()
642                 {
643                         // Managed and native threads are currently bound together.
644                 }
645
646                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
647                 public static void EndThreadAffinity ()
648                 {
649                         // Managed and native threads are currently bound together.
650                 }
651
652                 public ApartmentState GetApartmentState ()
653                 {
654                         return (ApartmentState)Internal.apartment_state;
655                 }
656
657                 public void SetApartmentState (ApartmentState state)
658                 {
659                         if (!TrySetApartmentState (state))
660                                 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
661                 }
662
663                 public bool TrySetApartmentState (ApartmentState state) 
664                 {
665                         if ((ThreadState & ThreadState.Unstarted) == 0)
666                                 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
667
668                         if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown && 
669                             (ApartmentState)Internal.apartment_state != state)
670                                 return false;
671
672                         Internal.apartment_state = (byte)state;
673
674                         return true;
675                 }
676                 
677                 [ComVisible (false)]
678                 public override int GetHashCode ()
679                 {
680                         return ManagedThreadId;
681                 }
682
683                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
684                 internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
685
686                 // This is a mono extension to gather the stack traces for all running threads
687                 internal static Dictionary<Thread, StackTrace> Mono_GetStackTraces () {
688                         Thread[] threads;
689                         object[] stack_frames;
690
691                         GetStackTraces (out threads, out stack_frames);
692
693                         var res = new Dictionary<Thread, StackTrace> ();
694                         for (int i = 0; i < threads.Length; ++i)
695                                 res [threads [i]] = new StackTrace ((StackFrame[])stack_frames [i]);
696                         return res;
697                 }
698
699 #if !MONO_FEATURE_THREAD_SUSPEND_RESUME
700                 [Obsolete ("Thread.Suspend is not supported on the current platform.", true)]
701                 public void Suspend ()
702                 {
703                         throw new PlatformNotSupportedException ("Thread.Suspend is not supported on the current platform.");
704                 }
705
706                 [Obsolete ("Thread.Resume is not supported on the current platform.", true)]
707                 public void Resume ()
708                 {
709                         throw new PlatformNotSupportedException ("Thread.Resume is not supported on the current platform.");
710                 }
711 #endif
712
713                 public void DisableComObjectEagerCleanup ()
714                 {
715                         throw new PlatformNotSupportedException ();
716                 }
717         }
718 }