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