[threads] Remove mono_threads_create_thread (#4411)
[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                 IntPtr unused3;
55                 /* accessed only from unmanaged code */
56                 private IntPtr name;
57                 private int name_len; 
58                 private ThreadState state;
59                 private object abort_exc;
60                 private int abort_state_handle;
61                 /* thread_id is only accessed from unmanaged code */
62                 internal Int64 thread_id;
63                 private IntPtr debugger_thread; // FIXME switch to bool as soon as CI testing with corlib version bump works
64                 private UIntPtr static_data; /* GC-tracked */
65                 private IntPtr runtime_thread_info;
66                 /* current System.Runtime.Remoting.Contexts.Context instance
67                    keep as an object to avoid triggering its class constructor when not needed */
68                 private object current_appcontext;
69                 private object root_domain_thread;
70                 internal byte[] _serialized_principal;
71                 internal int _serialized_principal_version;
72                 private IntPtr appdomain_refs;
73                 private int interruption_requested;
74                 private IntPtr synch_cs;
75                 internal bool threadpool_thread;
76                 private bool thread_interrupt_requested;
77                 /* These are used from managed code */
78                 internal int stack_size;
79                 internal byte apartment_state;
80                 internal volatile int critical_region_level;
81                 internal int managed_id;
82                 private int small_id;
83                 private IntPtr manage_callback;
84                 private IntPtr interrupt_on_stop;
85                 private IntPtr flags;
86                 private IntPtr thread_pinning_ref;
87                 private IntPtr abort_protected_block_count;
88                 private int priority = (int) ThreadPriority.Normal;
89                 private IntPtr owned_mutex;
90                 private IntPtr suspended_event;
91                 private int self_suspended;
92                 /* 
93                  * These fields are used to avoid having to increment corlib versions
94                  * when a new field is added to the unmanaged MonoThread structure.
95                  */
96                 private IntPtr unused1;
97                 private IntPtr unused2;
98
99                 /* This is used only to check that we are in sync between the representation
100                  * of MonoInternalThread in native and InternalThread in managed
101                  *
102                  * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */
103                 private IntPtr last;
104                 #endregion
105 #pragma warning restore 169, 414, 649
106
107                 // Closes the system thread handle
108                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
109                 private extern void Thread_free_internal();
110
111                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
112                 ~InternalThread() {
113                         Thread_free_internal();
114                 }
115         }
116
117         [StructLayout (LayoutKind.Sequential)]
118         public sealed partial class Thread {
119 #pragma warning disable 414             
120                 #region Sync with metadata/object-internals.h
121                 private InternalThread internal_thread;
122                 object m_ThreadStartArg;
123                 object pending_exception;
124                 #endregion
125 #pragma warning restore 414
126
127                 IPrincipal principal;
128                 int principal_version;
129
130                 // the name of current_thread is
131                 // important because they are used by the runtime.
132
133                 [ThreadStatic]
134                 static Thread current_thread;
135
136                 // can be both a ThreadStart and a ParameterizedThreadStart
137                 private MulticastDelegate m_Delegate;
138
139                 private ExecutionContext m_ExecutionContext;    // this call context follows the logical thread
140
141                 private bool m_ExecutionContextBelongsToOuterScope;
142
143                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
144                 private extern void ConstructInternalThread ();
145
146                 private InternalThread Internal {
147                         get {
148                                 if (internal_thread == null)
149                                         ConstructInternalThread ();
150                                 return internal_thread;
151                         }
152                 }
153
154                 public static Context CurrentContext {
155                         [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
156                         get {
157                                 return(AppDomain.InternalGetContext ());
158                         }
159                 }
160
161                 /*
162                  * These two methods return an array in the target
163                  * domain with the same content as the argument.  If
164                  * the argument is already in the target domain, then
165                  * the argument is returned, otherwise a copy.
166                  */
167                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
168                 private extern static byte[] ByteArrayToRootDomain (byte[] arr);
169
170                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
171                 private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
172
173                 static void DeserializePrincipal (Thread th)
174                 {
175                         MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
176                         int type = ms.ReadByte ();
177                         if (type == 0) {
178                                 BinaryFormatter bf = new BinaryFormatter ();
179                                 th.principal = (IPrincipal) bf.Deserialize (ms);
180                                 th.principal_version = th.Internal._serialized_principal_version;
181                         } else if (type == 1) {
182                                 BinaryReader reader = new BinaryReader (ms);
183                                 string name = reader.ReadString ();
184                                 string auth_type = reader.ReadString ();
185                                 int n_roles = reader.ReadInt32 ();
186                                 string [] roles = null;
187                                 if (n_roles >= 0) {
188                                         roles = new string [n_roles];
189                                         for (int i = 0; i < n_roles; i++)
190                                                 roles [i] = reader.ReadString ();
191                                 }
192                                 th.principal = new GenericPrincipal (new GenericIdentity (name, auth_type), roles);
193                         } else if (type == 2 || type == 3) {
194                                 string [] roles = type == 2 ? null : new string [0];
195                                 th.principal = new GenericPrincipal (new GenericIdentity ("", ""), roles);
196                         }
197                 }
198
199                 static void SerializePrincipal (Thread th, IPrincipal value)
200                 {
201                         MemoryStream ms = new MemoryStream ();
202                         bool done = false;
203                         if (value.GetType () == typeof (GenericPrincipal)) {
204                                 GenericPrincipal gp = (GenericPrincipal) value;
205                                 if (gp.Identity != null && gp.Identity.GetType () == typeof (GenericIdentity)) {
206                                         GenericIdentity id = (GenericIdentity) gp.Identity;
207                                         if (id.Name == "" && id.AuthenticationType == "") {
208                                                 if (gp.Roles == null) {
209                                                         ms.WriteByte (2);
210                                                         done = true;
211                                                 } else if (gp.Roles.Length == 0) {
212                                                         ms.WriteByte (3);
213                                                         done = true;
214                                                 }
215                                         } else {
216                                                 ms.WriteByte (1);
217                                                 BinaryWriter br = new BinaryWriter (ms);
218                                                 br.Write (gp.Identity.Name);
219                                                 br.Write (gp.Identity.AuthenticationType);
220                                                 string [] roles = gp.Roles;
221                                                 if  (roles == null) {
222                                                         br.Write ((int) (-1));
223                                                 } else {
224                                                         br.Write (roles.Length);
225                                                         foreach (string s in roles) {
226                                                                 br.Write (s);
227                                                         }
228                                                 }
229                                                 br.Flush ();
230                                                 done = true;
231                                         }
232                                 }
233                         }
234                         if (!done) {
235                                 ms.WriteByte (0);
236                                 BinaryFormatter bf = new BinaryFormatter ();
237                                 try {
238                                         bf.Serialize (ms, value);
239                                 } catch {}
240                         }
241                         th.Internal._serialized_principal = ByteArrayToRootDomain (ms.ToArray ());
242                 }
243
244                 public static IPrincipal CurrentPrincipal {
245                         get {
246                                 Thread th = CurrentThread;
247
248                                 if (th.principal_version != th.Internal._serialized_principal_version)
249                                         th.principal = null;
250
251                                 if (th.principal != null)
252                                         return th.principal;
253
254                                 if (th.Internal._serialized_principal != null) {
255                                         try {
256                                                 DeserializePrincipal (th);
257                                                 return th.principal;
258                                         } catch {}
259                                 }
260
261                                 th.principal = GetDomain ().DefaultPrincipal;
262                                 th.principal_version = th.Internal._serialized_principal_version;
263                                 return th.principal;
264                         }
265                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
266                         set {
267                                 Thread th = CurrentThread;
268
269                                 if (value != GetDomain ().DefaultPrincipal) {
270                                         ++th.Internal._serialized_principal_version;
271                                         try {
272                                                 SerializePrincipal (th, value);
273                                         } catch (Exception) {
274                                                 th.Internal._serialized_principal = null;
275                                         }
276                                         th.principal_version = th.Internal._serialized_principal_version;
277                                 } else {
278                                         th.Internal._serialized_principal = null;
279                                 }
280
281                                 th.principal = value;
282                         }
283                 }
284
285                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
286                 private extern static Thread GetCurrentThread ();
287
288                 public static Thread CurrentThread {
289                         [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
290                         get {
291                                 Thread current = current_thread;
292                                 if (current != null)
293                                         return current;
294                                 // This will set the current_thread tls variable
295                                 return GetCurrentThread ();
296                         }
297                 }
298
299                 internal static int CurrentThreadId {
300                         get {
301                                 return (int)(CurrentThread.internal_thread.thread_id);
302                         }
303                 }
304
305                 public static AppDomain GetDomain() {
306                         return AppDomain.CurrentDomain;
307                 }
308
309                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
310                 public extern static int GetDomainID();
311
312                 // Returns the system thread handle
313                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
314                 private extern IntPtr Thread_internal (MulticastDelegate start);
315
316                 private Thread (InternalThread it) {
317                         internal_thread = it;
318                 }
319                 
320                 // part of ".NETPortable,Version=v4.0,Profile=Profile3" i.e. FX4 and SL4
321                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
322                 ~Thread ()
323                 {
324                 }
325
326                 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
327                 public ApartmentState ApartmentState {
328                         get {
329                                 if ((ThreadState & ThreadState.Stopped) != 0)
330                                         throw new ThreadStateException ("Thread is dead; state can not be accessed.");
331
332                                 return (ApartmentState)Internal.apartment_state;
333                         }
334
335                         set {
336                                 TrySetApartmentState (value);
337                         }
338                 }
339
340                 public bool IsThreadPoolThread {
341                         get {
342                                 return IsThreadPoolThreadInternal;
343                         }
344                 }
345
346                 internal bool IsThreadPoolThreadInternal {
347                         get {
348                                 return Internal.threadpool_thread;
349                         }
350                         set {
351                                 Internal.threadpool_thread = value;
352                         }
353                 }
354
355                 public bool IsAlive {
356                         get {
357                                 ThreadState curstate = GetState (Internal);
358                                 
359                                 if((curstate & ThreadState.Aborted) != 0 ||
360                                    (curstate & ThreadState.Stopped) != 0 ||
361                                    (curstate & ThreadState.Unstarted) != 0) {
362                                         return(false);
363                                 } else {
364                                         return(true);
365                                 }
366                         }
367                 }
368
369                 public bool IsBackground {
370                         get {
371                                 ThreadState thread_state = GetState (Internal);
372                                 if ((thread_state & ThreadState.Stopped) != 0)
373                                         throw new ThreadStateException ("Thread is dead; state can not be accessed.");
374
375                                 return (thread_state & ThreadState.Background) != 0;
376                         }
377                         
378                         set {
379                                 if (value) {
380                                         SetState (Internal, ThreadState.Background);
381                                 } else {
382                                         ClrState (Internal, ThreadState.Background);
383                                 }
384                         }
385                 }
386
387                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
388                 private extern static string GetName_internal (InternalThread thread);
389
390                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
391                 private extern static void SetName_internal (InternalThread thread, String name);
392
393                 /* 
394                  * The thread name must be shared by appdomains, so it is stored in
395                  * unmanaged code.
396                  */
397
398                 public string Name {
399                         get {
400                                 return GetName_internal (Internal);
401                         }
402                         
403                         set {
404                                 SetName_internal (Internal, value);
405                         }
406                 }
407
408                 public ThreadState ThreadState {
409                         get {
410                                 return GetState (Internal);
411                         }
412                 }
413
414 #if MONO_FEATURE_THREAD_ABORT
415                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
416                 private extern static void Abort_internal (InternalThread thread, object stateInfo);
417
418                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
419                 public void Abort () 
420                 {
421                         Abort_internal (Internal, null);
422                 }
423
424                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
425                 public void Abort (object stateInfo) 
426                 {
427                         Abort_internal (Internal, stateInfo);
428                 }
429
430                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
431                 extern object GetAbortExceptionState ();
432
433                 internal object AbortReason {
434                         get {
435                                 return GetAbortExceptionState ();
436                         }
437                 }
438
439                 void ClearAbortReason ()
440                 {
441                 }
442 #else
443                 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
444                 public void Abort ()
445                 {
446                         throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
447                 }
448
449                 [Obsolete ("Thread.Abort is not supported on the current platform.", true)]
450                 public void Abort (object stateInfo)
451                 {
452                         throw new PlatformNotSupportedException ("Thread.Abort is not supported on the current platform.");
453                 }
454
455                 [Obsolete ("Thread.ResetAbort is not supported on the current platform.", true)]
456                 public static void ResetAbort ()
457                 {
458                         throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
459                 }
460
461                 internal object AbortReason {
462                         get {
463                                 throw new PlatformNotSupportedException ("Thread.ResetAbort is not supported on the current platform.");
464                         }
465                 }
466 #endif // MONO_FEATURE_THREAD_ABORT
467
468                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
469                 private extern static void SpinWait_nop ();
470
471
472                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
473                 public static void SpinWait (int iterations) 
474                 {
475                         if (iterations < 0)
476                                 return;
477                         while (iterations-- > 0)
478                         {
479                                 SpinWait_nop ();
480                         }
481                 }
482
483                 void StartInternal (IPrincipal principal, ref StackCrawlMark stackMark)
484                 {
485 #if FEATURE_ROLE_BASED_SECURITY
486                         Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
487 #endif
488
489                         // Thread_internal creates and starts the new thread, 
490                         if (Thread_internal(m_Delegate) == IntPtr.Zero)
491                                 throw new SystemException ("Thread creation failed.");
492
493                         m_ThreadStartArg = null;
494                 }
495
496                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
497                 extern private static void SetState (InternalThread thread, ThreadState set);
498
499                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
500                 extern private static void ClrState (InternalThread thread, ThreadState clr);
501
502                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
503                 extern private static ThreadState GetState (InternalThread thread);
504
505                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
506                 extern public static byte VolatileRead (ref byte address);
507                 
508                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
509                 extern public static double VolatileRead (ref double address);
510                 
511                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
512                 extern public static short VolatileRead (ref short address);
513                 
514                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
515                 extern public static int VolatileRead (ref int address);
516                 
517                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
518                 extern public static long VolatileRead (ref long address);
519                 
520                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
521                 extern public static IntPtr VolatileRead (ref IntPtr address);
522                 
523                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
524                 extern public static object VolatileRead (ref object address);
525
526                 [CLSCompliant(false)]
527                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
528                 extern public static sbyte VolatileRead (ref sbyte address);
529                 
530                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
531                 extern public static float VolatileRead (ref float address);
532
533                 [CLSCompliant (false)]
534                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
535                 extern public static ushort VolatileRead (ref ushort address);
536
537                 [CLSCompliant (false)]
538                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
539                 extern public static uint VolatileRead (ref uint address);
540
541                 [CLSCompliant (false)]
542                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
543                 extern public static ulong VolatileRead (ref ulong address);
544
545                 [CLSCompliant (false)]
546                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
547                 extern public static UIntPtr VolatileRead (ref UIntPtr address);
548
549                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
550                 extern public static void VolatileWrite (ref byte address, byte value);
551                 
552                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
553                 extern public static void VolatileWrite (ref double address, double value);
554                 
555                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
556                 extern public static void VolatileWrite (ref short address, short value);
557                 
558                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
559                 extern public static void VolatileWrite (ref int address, int value);
560                 
561                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
562                 extern public static void VolatileWrite (ref long address, long value);
563                 
564                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
565                 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
566                 
567                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
568                 extern public static void VolatileWrite (ref object address, object value);
569
570                 [CLSCompliant(false)]
571                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
572                 extern public static void VolatileWrite (ref sbyte address, sbyte value);
573                 
574                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
575                 extern public static void VolatileWrite (ref float address, float value);
576
577                 [CLSCompliant (false)]
578                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
579                 extern public static void VolatileWrite (ref ushort address, ushort value);
580
581                 [CLSCompliant (false)]
582                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
583                 extern public static void VolatileWrite (ref uint address, uint value);
584
585                 [CLSCompliant (false)]
586                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
587                 extern public static void VolatileWrite (ref ulong address, ulong value);
588
589                 [CLSCompliant (false)]
590                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
591                 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
592                 
593                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
594                 extern static int SystemMaxStackStize ();
595
596                 static int GetProcessDefaultStackSize (int maxStackSize)
597                 {
598                         if (maxStackSize == 0)
599                                 return 0;
600
601                         if (maxStackSize < 131072) // make sure stack is at least 128k big
602                                 return 131072;
603
604                         int page_size = Environment.GetPageSize ();
605
606                         if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
607                                 maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
608
609                         /* Respect the max stack size imposed by the system*/
610                         return Math.Min (maxStackSize, SystemMaxStackStize ());
611                 }
612
613                 void SetStart (MulticastDelegate start, int maxStackSize)
614                 {
615                         m_Delegate = start;
616                         Internal.stack_size = maxStackSize;
617                 }
618
619                 public int ManagedThreadId {
620                         [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
621                         get {
622                                 return Internal.managed_id;
623                         }
624                 }
625
626                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
627                 public static void BeginCriticalRegion ()
628                 {
629                         CurrentThread.Internal.critical_region_level++;
630                 }
631
632                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
633                 public static void EndCriticalRegion ()
634                 {
635                         CurrentThread.Internal.critical_region_level--;
636                 }
637
638                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
639                 public static void BeginThreadAffinity ()
640                 {
641                         // Managed and native threads are currently bound together.
642                 }
643
644                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
645                 public static void EndThreadAffinity ()
646                 {
647                         // Managed and native threads are currently bound together.
648                 }
649
650                 public ApartmentState GetApartmentState ()
651                 {
652                         return (ApartmentState)Internal.apartment_state;
653                 }
654
655                 public void SetApartmentState (ApartmentState state)
656                 {
657                         if (!TrySetApartmentState (state))
658                                 throw new InvalidOperationException ("Failed to set the specified COM apartment state.");
659                 }
660
661                 public bool TrySetApartmentState (ApartmentState state) 
662                 {
663                         if ((ThreadState & ThreadState.Unstarted) == 0)
664                                 throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
665
666                         if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown && 
667                             (ApartmentState)Internal.apartment_state != state)
668                                 return false;
669
670                         Internal.apartment_state = (byte)state;
671
672                         return true;
673                 }
674                 
675                 [ComVisible (false)]
676                 public override int GetHashCode ()
677                 {
678                         return ManagedThreadId;
679                 }
680
681                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
682                 internal static extern void GetStackTraces (out Thread[] threads, out object[] stack_frames);
683
684                 // This is a mono extension to gather the stack traces for all running threads
685                 internal static Dictionary<Thread, StackTrace> Mono_GetStackTraces () {
686                         Thread[] threads;
687                         object[] stack_frames;
688
689                         GetStackTraces (out threads, out stack_frames);
690
691                         var res = new Dictionary<Thread, StackTrace> ();
692                         for (int i = 0; i < threads.Length; ++i)
693                                 res [threads [i]] = new StackTrace ((StackFrame[])stack_frames [i]);
694                         return res;
695                 }
696
697 #if !MONO_FEATURE_THREAD_SUSPEND_RESUME
698                 [Obsolete ("Thread.Suspend is not supported on the current platform.", true)]
699                 public void Suspend ()
700                 {
701                         throw new PlatformNotSupportedException ("Thread.Suspend is not supported on the current platform.");
702                 }
703
704                 [Obsolete ("Thread.Resume is not supported on the current platform.", true)]
705                 public void Resume ()
706                 {
707                         throw new PlatformNotSupportedException ("Thread.Resume is not supported on the current platform.");
708                 }
709 #endif
710
711                 public void DisableComObjectEagerCleanup ()
712                 {
713                         throw new PlatformNotSupportedException ();
714                 }
715         }
716 }