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