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