Wed Mar 29 18:29:55 CEST 2006 Paolo Molaro <lupus@ximian.com>
[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-2005 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;
40 using System.Security;
41
42 #if NET_2_0
43 using System.Runtime.ConstrainedExecution;
44 #endif
45
46 namespace System.Threading {
47
48         [ClassInterface (ClassInterfaceType.None)]
49 #if NET_2_0
50         [ComVisible (true)]
51         [ComDefaultInterface (typeof (_Thread))]
52 #endif
53         public sealed class Thread : _Thread {
54
55                 #region Sync with metadata/object-internals.h
56                 int lock_thread_id;
57                 // stores a thread handle
58                 private IntPtr system_thread_handle;
59
60                 /* Note this is an opaque object (an array), not a CultureInfo */
61                 private object cached_culture_info;
62                 private IntPtr unused0;
63                 private bool threadpool_thread;
64                 /* accessed only from unmanaged code */
65                 private IntPtr name;
66                 private int name_len; 
67                 private ThreadState state = ThreadState.Unstarted;
68                 private object abort_exc;
69                 internal object abort_state;
70                 /* thread_id is only accessed from unmanaged code */
71                 private Int64 thread_id;
72                 
73                 /* start_notify is used by the runtime to signal that Start()
74                  * is ok to return
75                  */
76                 private IntPtr start_notify;
77                 private IntPtr stack_ptr;
78                 private IntPtr static_data;
79                 private IntPtr jit_data;
80                 private IntPtr lock_data;
81                 Context current_appcontext;
82                 int stack_size;
83                 object start_obj;
84                 private IntPtr appdomain_refs;
85                 private bool interruption_requested;
86                 private IntPtr suspend_event;
87                 private IntPtr suspended_event;
88                 private IntPtr resume_event;
89                 /* Don't lock on synch_lock in managed code, since it can result in deadlocks */
90                 private object synch_lock = new Object();
91                 private IntPtr serialized_culture_info;
92                 private int serialized_culture_info_len;
93                 private IntPtr serialized_ui_culture_info;
94                 private int serialized_ui_culture_info_len;
95                 private ExecutionContext _ec;
96                 /* 
97                  * These fields are used to avoid having to increment corlib versions
98                  * when a new field is added to the unmanaged MonoThread structure.
99                  */
100                 private IntPtr unused1;
101                 private IntPtr unused2;
102                 private IntPtr unused3;
103                 private IntPtr unused4;
104                 private IntPtr unused5;
105                 private IntPtr unused6;
106                 private IntPtr unused7;
107                 #endregion
108
109                 // the name of local_slots is important as it's used by the runtime.
110                 [ThreadStatic] 
111                 static object[] local_slots;
112
113                 // can be both a ThreadSart and a ParameterizedThreadStart
114                 private MulticastDelegate threadstart;
115                 private string thread_name=null;
116                 
117                 private IPrincipal _principal;
118
119                 public static Context CurrentContext {
120                         [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
121                         get {
122                                 return(AppDomain.InternalGetContext ());
123                         }
124                 }
125
126                 public static IPrincipal CurrentPrincipal {
127                         get {
128                                 IPrincipal p = null;
129                                 Thread th = CurrentThread;
130                                 lock (th) {
131                                         p = th._principal;
132                                         if (p == null) {
133                                                 p = GetDomain ().DefaultPrincipal;
134                                                 th._principal = p;
135                                         }
136                                 }
137                                 return p;
138                         }
139                         [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
140                         set {
141                                 CurrentThread._principal = value;
142                         }
143                 }
144
145                 // Looks up the object associated with the current thread
146                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
147                 private extern static Thread CurrentThread_internal();
148                 
149                 public static Thread CurrentThread {
150 #if NET_2_0
151                         [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
152 #endif
153                         get {
154                                 return(CurrentThread_internal());
155                         }
156                 }
157
158                 internal static int CurrentThreadId {
159                         get {
160                                 return (int)(CurrentThread.thread_id);
161                         }
162                 }
163
164                 // Stores a hash keyed by strings of LocalDataStoreSlot objects
165                 static Hashtable datastorehash;
166                 private static object datastore_lock = new object ();
167                 
168                 private static void InitDataStoreHash () {
169                         lock (datastore_lock) {
170                                 if (datastorehash == null) {
171                                         datastorehash = Hashtable.Synchronized(new Hashtable());
172                                 }
173                         }
174                 }
175                 
176                 public static LocalDataStoreSlot AllocateNamedDataSlot (string name) {
177                         lock (datastore_lock) {
178                                 if (datastorehash == null)
179                                         InitDataStoreHash ();
180                                 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
181                                 if (slot != null) {
182                                         // This exception isnt documented (of
183                                         // course) but .net throws it
184                                         throw new ArgumentException("Named data slot already added");
185                                 }
186                         
187                                 slot = AllocateDataSlot ();
188
189                                 datastorehash.Add (name, slot);
190
191                                 return slot;
192                         }
193                 }
194
195                 public static void FreeNamedDataSlot (string name) {
196                         lock (datastore_lock) {
197                                 if (datastorehash == null)
198                                         InitDataStoreHash ();
199                                 LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
200
201                                 if (slot != null) {
202                                         datastorehash.Remove (slot);
203                                 }
204                         }
205                 }
206
207                 public static LocalDataStoreSlot AllocateDataSlot () {
208                         return new LocalDataStoreSlot (true);
209                 }
210
211                 public static object GetData (LocalDataStoreSlot slot) {
212                         object[] slots = local_slots;
213                         if (slot == null)
214                                 throw new ArgumentNullException ("slot");
215                         if (slots != null && slot.slot < slots.Length)
216                                 return slots [slot.slot];
217                         return null;
218                 }
219
220                 public static void SetData (LocalDataStoreSlot slot, object data) {
221                         object[] slots = local_slots;
222                         if (slot == null)
223                                 throw new ArgumentNullException ("slot");
224                         if (slots == null) {
225                                 slots = new object [slot.slot + 2];
226                                 local_slots = slots;
227                         } else if (slot.slot >= slots.Length) {
228                                 object[] nslots = new object [slot.slot + 2];
229                                 slots.CopyTo (nslots, 0);
230                                 slots = nslots;
231                                 local_slots = slots;
232                         }
233                         slots [slot.slot] = data;
234                 }
235
236                 public static AppDomain GetDomain() {
237                         return AppDomain.CurrentDomain;
238                 }
239
240                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
241                 public extern static int GetDomainID();
242
243                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
244                 internal extern static void FreeLocalSlotValues (int slot, bool thread_local);
245
246                 public static LocalDataStoreSlot GetNamedDataSlot(string name) {
247                         lock (datastore_lock) {
248                                 if (datastorehash == null)
249                                         InitDataStoreHash ();
250                                 LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
251
252                                 if(slot==null) {
253                                         slot=AllocateNamedDataSlot(name);
254                                 }
255                         
256                                 return(slot);
257                         }
258                 }
259                 
260                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
261                 private extern static void ResetAbort_internal();
262
263                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
264                 public static void ResetAbort ()
265                 {
266                         ResetAbort_internal ();
267                 }
268
269                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
270                 private extern static void Sleep_internal(int ms);
271
272                 public static void Sleep(int millisecondsTimeout) {
273                         if((millisecondsTimeout<0) && (millisecondsTimeout != Timeout.Infinite)) {
274                                 throw new ArgumentException("Negative timeout");
275                         }
276                         Sleep_internal(millisecondsTimeout);
277                 }
278
279                 public static void Sleep(TimeSpan timeout) {
280                         // LAMESPEC: says to throw ArgumentException too
281                         int ms=Convert.ToInt32(timeout.TotalMilliseconds);
282                         
283                         if(ms < 0 || ms > Int32.MaxValue) {
284                                 throw new ArgumentOutOfRangeException("Timeout out of range");
285                         }
286
287                         Sleep_internal(ms);
288                 }
289
290                 // Returns the system thread handle
291                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
292                 private extern IntPtr Thread_internal (MulticastDelegate start);
293
294                 public Thread(ThreadStart start) {
295                         if(start==null) {
296                                 throw new ArgumentNullException("Null ThreadStart");
297                         }
298                         threadstart=start;
299                 }
300
301                 [MonoTODO]
302 #if NET_2_0
303                 [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
304 #endif
305                 public ApartmentState ApartmentState {
306                         get {
307                                 return(ApartmentState.Unknown);
308                         }
309                         
310                         set {
311                         }
312                 }
313
314                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
315                 private static extern int current_lcid ();
316
317                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
318                 private extern CultureInfo GetCachedCurrentCulture ();
319
320                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
321                 private extern byte[] GetSerializedCurrentCulture ();
322
323                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
324                 private extern void SetCachedCurrentCulture (CultureInfo culture);
325
326                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
327                 private extern void SetSerializedCurrentCulture (byte[] culture);
328
329                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
330                 private extern CultureInfo GetCachedCurrentUICulture ();
331
332                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
333                 private extern byte[] GetSerializedCurrentUICulture ();
334
335                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
336                 private extern void SetCachedCurrentUICulture (CultureInfo culture);
337
338                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
339                 private extern void SetSerializedCurrentUICulture (byte[] culture);
340
341                 /* If the current_lcid() isn't known by CultureInfo,
342                  * it will throw an exception which may cause
343                  * String.Concat to try and recursively look up the
344                  * CurrentCulture, which will throw an exception, etc.
345                  * Use a boolean to short-circuit this scenario.
346                  */
347                 private static bool in_currentculture=false;
348
349                 static object culture_lock = new object ();
350                 
351                 /*
352                  * Thread objects are shared between appdomains, and CurrentCulture
353                  * should always return an object in the calling appdomain. See bug
354                  * http://bugzilla.ximian.com/show_bug.cgi?id=50049 for more info.
355                  * This is hard to implement correctly and efficiently, so the current
356                  * implementation is not perfect: changes made in one appdomain to the 
357                  * state of the current cultureinfo object are not visible to other 
358                  * appdomains.
359                  */             
360                 public CultureInfo CurrentCulture {
361                         get {
362                                 if (in_currentculture)
363                                         /* Bail out */
364                                         return CultureInfo.InvariantCulture;
365
366                                 CultureInfo culture = GetCachedCurrentCulture ();
367                                 if (culture != null)
368                                         return culture;
369
370                                 byte[] arr = GetSerializedCurrentCulture ();
371                                 if (arr == null) {
372                                         lock (culture_lock) {
373                                                 in_currentculture=true;
374                                                 culture = CultureInfo.ConstructCurrentCulture ();
375                                                 //
376                                                 // Don't serialize the culture in this case to avoid
377                                                 // initializing the serialization infrastructure in the
378                                                 // common case when the culture is not set explicitly.
379                                                 //
380                                                 SetCachedCurrentCulture (culture);
381                                                 in_currentculture = false;
382                                                 return culture;
383                                         }
384                                 }
385
386                                 /*
387                                  * No cultureinfo object exists for this domain, so create one
388                                  * by deserializing the serialized form.
389                                  */
390                                 in_currentculture = true;
391                                 try {
392                                         BinaryFormatter bf = new BinaryFormatter ();
393                                         MemoryStream ms = new MemoryStream (arr);
394                                         culture = (CultureInfo)bf.Deserialize (ms);
395                                         SetCachedCurrentCulture (culture);
396                                 } finally {
397                                         in_currentculture = false;
398                                 }
399
400                                 return culture;
401                         }
402                         
403                         [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
404                         set {
405                                 if (value == null)
406                                         throw new ArgumentNullException ("value");
407
408                                 value.CheckNeutral ();
409                                 in_currentculture = true;
410                                 try {
411                                         BinaryFormatter bf = new BinaryFormatter();
412                                         MemoryStream ms = new MemoryStream ();
413                                         bf.Serialize (ms, value);
414
415                                         SetCachedCurrentCulture (value);
416                                         SetSerializedCurrentCulture (ms.GetBuffer ());
417                                 } finally {
418                                         in_currentculture = false;
419                                 }
420                         }
421                 }
422
423                 public CultureInfo CurrentUICulture {
424                         get {
425                                 if (in_currentculture)
426                                         /* Bail out */
427                                         return CultureInfo.InvariantCulture;
428
429                                 CultureInfo culture = GetCachedCurrentUICulture ();
430                                 if (culture != null)
431                                         return culture;
432
433                                 byte[] arr = GetSerializedCurrentUICulture ();
434                                 if (arr == null) {
435                                         lock (culture_lock) {
436                                                 in_currentculture=true;
437                                                 /* We don't
438                                                  * distinguish
439                                                  * between
440                                                  * System and
441                                                  * UI cultures
442                                                  */
443                                                 culture = CultureInfo.ConstructCurrentUICulture ();
444                                                 //
445                                                 // Don't serialize the culture in this case to avoid
446                                                 // initializing the serialization infrastructure in the
447                                                 // common case when the culture is not set explicitly.
448                                                 //
449                                                 SetCachedCurrentUICulture (culture);
450                                                 in_currentculture = false;
451                                                 return culture;
452                                         }
453                                 }
454
455                                 /*
456                                  * No cultureinfo object exists for this domain, so create one
457                                  * by deserializing the serialized form.
458                                  */
459                                 in_currentculture = true;
460                                 try {
461                                         BinaryFormatter bf = new BinaryFormatter ();
462                                         MemoryStream ms = new MemoryStream (arr);
463                                         culture = (CultureInfo)bf.Deserialize (ms);
464                                         SetCachedCurrentUICulture (culture);
465                                 }
466                                 finally {
467                                         in_currentculture = false;
468                                 }
469
470                                 return culture;
471                         }
472                         
473                         set {
474                                 in_currentculture = true;
475                                 
476                                 if (value == null)
477                                         throw new ArgumentNullException ("value");
478
479                                 try {
480                                         BinaryFormatter bf = new BinaryFormatter();
481                                         MemoryStream ms = new MemoryStream ();
482                                         bf.Serialize (ms, value);
483
484                                         SetCachedCurrentUICulture (value);
485                                         SetSerializedCurrentUICulture (ms.GetBuffer ());
486                                 } finally {
487                                         in_currentculture = false;
488                                 }
489                         }
490                 }
491
492                 public bool IsThreadPoolThread {
493                         get {
494                                 return IsThreadPoolThreadInternal;
495                         }
496                 }
497
498                 internal bool IsThreadPoolThreadInternal {
499                         get {
500                                 return threadpool_thread;
501                         }
502                         set {
503                                 threadpool_thread = value;
504                         }
505                 }
506
507                 public bool IsAlive {
508                         get {
509                                 ThreadState curstate = GetState ();
510                                 
511                                 if((curstate & ThreadState.Aborted) != 0 ||
512                                    (curstate & ThreadState.Stopped) != 0 ||
513                                    (curstate & ThreadState.Unstarted) != 0) {
514                                         return(false);
515                                 } else {
516                                         return(true);
517                                 }
518                         }
519                 }
520
521                 public bool IsBackground {
522                         get {
523                                 return (GetState () & ThreadState.Background) != 0;
524                         }
525                         
526                         set {
527                                 if (value) {
528                                         SetState (ThreadState.Background);
529                                 } else {
530                                         ClrState (ThreadState.Background);
531                                 }
532                         }
533                 }
534
535                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
536                 private extern string GetName_internal ();
537
538                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
539                 private extern void SetName_internal (String name);
540
541                 /* 
542                  * The thread name must be shared by appdomains, so it is stored in
543                  * unmanaged code.
544                  */
545
546                 public string Name {
547                         get {
548                                 return GetName_internal ();
549                         }
550                         
551                         set {
552                                 SetName_internal (value);
553                         }
554                 }
555
556                 [MonoTODO]
557                 public ThreadPriority Priority {
558                         get {
559                                 return(ThreadPriority.Lowest);
560                         }
561                         
562                         set {
563                         }
564                 }
565
566                 public ThreadState ThreadState {
567                         get {
568                                 return GetState ();
569                         }
570                 }
571
572                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
573                 private extern void Abort_internal (object stateInfo);
574
575                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
576                 public void Abort () 
577                 {
578                         Abort_internal (null);
579                 }
580
581                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
582                 public void Abort (object stateInfo) 
583                 {
584                         Abort_internal (stateInfo);
585                 }
586                 
587
588                 [MonoTODO]
589                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
590                 public void Interrupt ()
591                 {
592                         throw new NotImplementedException ();
593                 }
594
595                 // The current thread joins with 'this'. Set ms to 0 to block
596                 // until this actually exits.
597                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
598                 private extern bool Join_internal(int ms, IntPtr handle);
599                 
600                 public void Join()
601                 {
602                         Join_internal(Timeout.Infinite, system_thread_handle);
603                 }
604
605                 public bool Join(int millisecondsTimeout)
606                 {
607                         if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
608                                 throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
609
610                         return Join_internal(millisecondsTimeout, system_thread_handle);
611                 }
612
613                 public bool Join(TimeSpan timeout)
614                 {
615                         // LAMESPEC: says to throw ArgumentException too
616                         int ms=Convert.ToInt32(timeout.TotalMilliseconds);
617                         
618                         if(ms < 0 || ms > Int32.MaxValue) {
619                                 throw new ArgumentOutOfRangeException("timeout out of range");
620                         }
621                         return Join_internal(ms, system_thread_handle);
622                 }
623
624 #if NET_1_1
625                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
626                 public extern static void MemoryBarrier ();
627 #endif
628                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
629                 private extern void Resume_internal();
630
631 #if NET_2_0
632                 [Obsolete ("")]
633 #endif
634                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
635                 public void Resume () 
636                 {
637                         Resume_internal ();
638                 }
639
640                 [MonoTODO]
641 #if NET_2_0
642                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
643 #endif
644                 public static void SpinWait (int iterations) 
645                 {
646                         throw new NotImplementedException ();
647                 }
648
649                 public void Start() {
650                         // propagate informations from the original thread to the new thread
651 #if NET_2_0
652                         if (!ExecutionContext.IsFlowSuppressed ())
653                                 _ec = ExecutionContext.Capture ();
654 #else
655                         // before 2.0 this was only used for security (mostly CAS) so we
656                         // do this only if the security manager is active
657                         if (SecurityManager.SecurityEnabled)
658                                 _ec = ExecutionContext.Capture ();
659 #endif
660                         if (CurrentThread._principal != null)
661                                 _principal = CurrentThread._principal;
662
663                         // Thread_internal creates and starts the new thread, 
664                         if (Thread_internal(threadstart) == (IntPtr) 0)
665                                 throw new SystemException ("Thread creation failed.");
666                 }
667
668                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
669                 private extern void Suspend_internal();
670
671 #if NET_2_0
672                 [Obsolete ("")]
673 #endif
674                 [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
675                 public void Suspend ()
676                 {
677                         Suspend_internal ();
678                 }
679
680                 // Closes the system thread handle
681                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
682                 private extern void Thread_free_internal(IntPtr handle);
683
684 #if NET_2_0
685                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
686 #endif
687                 ~Thread() {
688                         // Free up the handle
689                         if (system_thread_handle != (IntPtr) 0)
690                                 Thread_free_internal(system_thread_handle);
691                 }
692
693                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
694                 extern private void SetState (ThreadState set);
695                 
696                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
697                 extern private void ClrState (ThreadState clr);
698                 
699                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
700                 extern private ThreadState GetState ();
701
702 #if NET_1_1
703                 
704                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
705                 extern public static byte VolatileRead (ref byte address);
706                 
707                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
708                 extern public static double VolatileRead (ref double address);
709                 
710                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
711                 extern public static short VolatileRead (ref short address);
712                 
713                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
714                 extern public static int VolatileRead (ref int address);
715                 
716                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
717                 extern public static long VolatileRead (ref long address);
718                 
719                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
720                 extern public static IntPtr VolatileRead (ref IntPtr address);
721                 
722                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
723                 extern public static object VolatileRead (ref object address);
724
725                 [CLSCompliant(false)]
726                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
727                 extern public static sbyte VolatileRead (ref sbyte address);
728                 
729                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
730                 extern public static float VolatileRead (ref float address);
731
732                 [CLSCompliant (false)]
733                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
734                 extern public static ushort VolatileRead (ref ushort address);
735
736                 [CLSCompliant (false)]
737                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
738                 extern public static uint VolatileRead (ref uint address);
739
740                 [CLSCompliant (false)]
741                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
742                 extern public static ulong VolatileRead (ref ulong address);
743
744                 [CLSCompliant (false)]
745                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
746                 extern public static UIntPtr VolatileRead (ref UIntPtr address);
747
748                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
749                 extern public static void VolatileWrite (ref byte address, byte value);
750                 
751                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
752                 extern public static void VolatileWrite (ref double address, double value);
753                 
754                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
755                 extern public static void VolatileWrite (ref short address, short value);
756                 
757                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
758                 extern public static void VolatileWrite (ref int address, int value);
759                 
760                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
761                 extern public static void VolatileWrite (ref long address, long value);
762                 
763                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
764                 extern public static void VolatileWrite (ref IntPtr address, IntPtr value);
765                 
766                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
767                 extern public static void VolatileWrite (ref object address, object value);
768
769                 [CLSCompliant(false)]
770                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
771                 extern public static void VolatileWrite (ref sbyte address, sbyte value);
772                 
773                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
774                 extern public static void VolatileWrite (ref float address, float value);
775
776                 [CLSCompliant (false)]
777                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
778                 extern public static void VolatileWrite (ref ushort address, ushort value);
779
780                 [CLSCompliant (false)]
781                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
782                 extern public static void VolatileWrite (ref uint address, uint value);
783
784                 [CLSCompliant (false)]
785                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
786                 extern public static void VolatileWrite (ref ulong address, ulong value);
787
788                 [CLSCompliant (false)]
789                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
790                 extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
791                 
792 #endif
793
794 #if NET_2_0
795                 public Thread (ThreadStart start, int maxStackSize)
796                 {
797                         if (start == null)
798                                 throw new ArgumentNullException ("start");
799                         if (maxStackSize < 131072)
800                                 throw new ArgumentException ("< 128 kb", "maxStackSize");
801
802                         threadstart = start;
803                         stack_size = maxStackSize;
804                 }
805
806                 public Thread (ParameterizedThreadStart start)
807                 {
808                         if (start == null)
809                                 throw new ArgumentNullException ("start");
810
811                         threadstart = start;
812                 }
813
814                 public Thread (ParameterizedThreadStart start, int maxStackSize)
815                 {
816                         if (start == null)
817                                 throw new ArgumentNullException ("start");
818                         if (maxStackSize < 131072)
819                                 throw new ArgumentException ("< 128 kb", "maxStackSize");
820
821                         threadstart = start;
822                         stack_size = maxStackSize;
823                 }
824
825                 [MonoTODO ("limited to CompressedStack support")]
826                 public ExecutionContext ExecutionContext {
827                         [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
828                         get {
829                                 if (_ec == null)
830                                         _ec = new ExecutionContext ();
831                                 return _ec;
832                         }
833                 }
834
835                 public int ManagedThreadId {
836                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
837                         get { return (int)thread_id; }
838                 }
839
840                 [MonoTODO]
841                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
842                 public static void BeginCriticalRegion ()
843                 {
844                         throw new NotImplementedException ();
845                 }
846
847                 [MonoTODO]
848                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
849                 public static void EndCriticalRegion ()
850                 {
851                         throw new NotImplementedException ();
852                 }
853
854                 [MonoTODO]
855                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
856                 public static void BeginThreadAffinity ()
857                 {
858                         throw new NotImplementedException ();
859                 }
860
861                 [MonoTODO]
862                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
863                 public static void EndThreadAffinity ()
864                 {
865                         throw new NotImplementedException ();
866                 }
867
868                 //
869                 // We disable warning 618, because we are accessing the
870                 // empty property ApartmentState which produces an Obsolete
871                 // message, but since its an empty routine needed for 1.x
872                 // we use it.
873                 //
874                 // Maybe we should later turn these into internal methods for 1.x
875                 // instead and have the property call these.
876                 
877                 
878                 [MonoTODO]
879                 public ApartmentState GetApartmentState ()
880                 {
881                         return this.ApartmentState;
882                 }
883
884                 [MonoTODO]
885                 public void SetApartmentState (ApartmentState state)
886                 {
887                         this.ApartmentState = state;
888                 }
889
890                 [MonoTODO]
891                 public bool TrySetApartmentState (ApartmentState state)
892                 {
893                         try {
894                                 this.ApartmentState = state;
895                                 return true;
896                         }
897                         catch (ArgumentException) {
898                                 throw;
899                         }
900                         catch {
901                                 return false;
902                         }
903                 }
904                 
905                 [ComVisible (false)]
906                 public override int GetHashCode ()
907                 {
908                         // ??? overridden but not guaranteed to be unique ???
909                         return (int)thread_id;
910                 }
911
912                 public void Start (object parameter)
913                 {
914                         start_obj = parameter;
915                         Start ();
916                 }
917 #else
918                 internal ExecutionContext ExecutionContext {
919                         get {
920                                 if (_ec == null)
921                                         _ec = new ExecutionContext ();
922                                 return _ec;
923                         }
924                 }
925 #endif
926
927                 // NOTE: This method doesn't show in the class library status page because
928                 // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
929                 // But it's there!
930                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
931                 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
932 #if NET_2_0
933                 [Obsolete ("see CompressedStack class")]
934 #endif
935 #if NET_1_1
936                 public
937 #else
938                 internal
939 #endif
940                 CompressedStack GetCompressedStack ()
941                 {
942                         // Note: returns null if no CompressedStack has been set.
943                         // However CompressedStack.GetCompressedStack returns an 
944                         // (empty?) CompressedStack instance.
945                         CompressedStack cs = ExecutionContext.SecurityContext.CompressedStack;
946                         return ((cs == null) || cs.IsEmpty ()) ? null : cs.CreateCopy ();
947                 }
948
949                 // NOTE: This method doesn't show in the class library status page because
950                 // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
951                 // But it's there!
952                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
953                 [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
954 #if NET_2_0
955                 [Obsolete ("see CompressedStack class")]
956 #endif
957 #if NET_1_1
958                 public
959 #else
960                 internal
961 #endif
962                 void SetCompressedStack (CompressedStack stack)
963                 {
964                         ExecutionContext.SecurityContext.CompressedStack = stack;
965                 }
966
967 #if NET_1_1
968                 void _Thread.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
969                 {
970                         throw new NotImplementedException ();
971                 }
972
973                 void _Thread.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
974                 {
975                         throw new NotImplementedException ();
976                 }
977
978                 void _Thread.GetTypeInfoCount (out uint pcTInfo)
979                 {
980                         throw new NotImplementedException ();
981                 }
982
983                 void _Thread.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
984                         IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
985                 {
986                         throw new NotImplementedException ();
987                 }
988 #endif
989         }
990 }