2006-07-04 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / corlib / System.Threading / Thread.cs
old mode 100755 (executable)
new mode 100644 (file)
index 3e07128..75321e5
@@ -5,11 +5,7 @@
 //   Dick Porter (dick@ximian.com)
 //
 // (C) Ximian, Inc.  http://www.ximian.com
-// Copyright (C) 2004 Novell (http://www.novell.com)
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 //
 
 using System.Runtime.Remoting.Contexts;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
 using System.Security.Permissions;
 using System.Security.Principal;
 using System.Globalization;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.IO;
 using System.Collections;
+using System.Security;
+
+#if NET_2_0
+using System.Runtime.ConstrainedExecution;
+#endif
+
+namespace System.Threading {
+
+       [ClassInterface (ClassInterfaceType.None)]
+#if NET_2_0
+       [ComVisible (true)]
+       [ComDefaultInterface (typeof (_Thread))]
+       public sealed class Thread : CriticalFinalizerObject, _Thread {
+#else
+       public sealed class Thread : _Thread {
+#endif
 
-namespace System.Threading
-{
-       public sealed class Thread
-       {
-               #region Sync with object.h
+               #region Sync with metadata/object-internals.h
+               int lock_thread_id;
                // stores a thread handle
                private IntPtr system_thread_handle;
-               
-               private CultureInfo current_culture;
-               private CultureInfo current_ui_culture;
+
+               /* Note this is an opaque object (an array), not a CultureInfo */
+               private object cached_culture_info;
+               private IntPtr unused0;
                private bool threadpool_thread;
                /* accessed only from unmanaged code */
                private IntPtr name;
@@ -56,7 +70,7 @@ namespace System.Threading
                private object abort_exc;
                internal object abort_state;
                /* thread_id is only accessed from unmanaged code */
-               private int thread_id;
+               private Int64 thread_id;
                
                /* start_notify is used by the runtime to signal that Start()
                 * is ok to return
@@ -66,16 +80,46 @@ namespace System.Threading
                private IntPtr static_data;
                private IntPtr jit_data;
                private IntPtr lock_data;
+               Context current_appcontext;
+               int stack_size;
+               object start_obj;
                private IntPtr appdomain_refs;
                private bool interruption_requested;
+               private IntPtr suspend_event;
+               private IntPtr suspended_event;
+               private IntPtr resume_event;
+               /* Don't lock on synch_lock in managed code, since it can result in deadlocks */
+               private object synch_lock = new Object();
+               private IntPtr serialized_culture_info;
+               private int serialized_culture_info_len;
+               private IntPtr serialized_ui_culture_info;
+               private int serialized_ui_culture_info_len;
+               private ExecutionContext _ec;
+               /* 
+                * These fields are used to avoid having to increment corlib versions
+                * when a new field is added to the unmanaged MonoThread structure.
+                */
+               private IntPtr unused1;
+               private IntPtr unused2;
+               private IntPtr unused3;
+               private IntPtr unused4;
+               private IntPtr unused5;
+               private IntPtr unused6;
+               private IntPtr unused7;
                #endregion
 
-               private ThreadStart threadstart;
+               // the name of local_slots is important as it's used by the runtime.
+               [ThreadStatic] 
+               static object[] local_slots;
+
+               // can be both a ThreadSart and a ParameterizedThreadStart
+               private MulticastDelegate threadstart;
                private string thread_name=null;
                
                private IPrincipal _principal;
-               
+
                public static Context CurrentContext {
+                       [SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
                        get {
                                return(AppDomain.InternalGetContext ());
                        }
@@ -94,8 +138,8 @@ namespace System.Threading
                                }
                                return p;
                        }
+                       [SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
                        set {
-                               new SecurityPermission (SecurityPermissionFlag.ControlPrincipal).Demand ();
                                CurrentThread._principal = value;
                        }
                }
@@ -105,6 +149,9 @@ namespace System.Threading
                private extern static Thread CurrentThread_internal();
                
                public static Thread CurrentThread {
+#if NET_2_0
+                       [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
                        get {
                                return(CurrentThread_internal());
                        }
@@ -112,91 +159,80 @@ namespace System.Threading
 
                internal static int CurrentThreadId {
                        get {
-                               return CurrentThread.thread_id;
+                               return (int)(CurrentThread.thread_id);
                        }
                }
 
-               // Looks up the slot hash for the current thread
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static Hashtable SlotHash_lookup();
-
-               // Stores the slot hash for the current thread
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern static void SlotHash_store(Hashtable slothash);
-
-               private static Hashtable GetTLSSlotHash() {
-                       Hashtable slothash=SlotHash_lookup();
-                       if(slothash==null) {
-                               // Not synchronised, because this is
-                               // thread specific anyway.
-                               slothash=new Hashtable();
-                               SlotHash_store(slothash);
-                       }
-
-                       return(slothash);
-               }
-               
-               internal static object ResetDataStoreStatus () {
-                       Hashtable slothash=SlotHash_lookup();
-                       SlotHash_store(null);
-                       return slothash;
-               }
-
-               internal static void RestoreDataStoreStatus (object data) {
-                       SlotHash_store((Hashtable)data);
-               }
-
-               public static LocalDataStoreSlot AllocateDataSlot() {
-                       LocalDataStoreSlot slot = new LocalDataStoreSlot();
-
-                       return(slot);
-               }
-
                // Stores a hash keyed by strings of LocalDataStoreSlot objects
                static Hashtable datastorehash;
-
+               private static object datastore_lock = new object ();
+               
                private static void InitDataStoreHash () {
-                       lock (typeof (Thread)) {
+                       lock (datastore_lock) {
                                if (datastorehash == null) {
                                        datastorehash = Hashtable.Synchronized(new Hashtable());
                                }
                        }
                }
                
-               public static LocalDataStoreSlot AllocateNamedDataSlot(string name) {
-                       lock (typeof (Thread)) {
+               public static LocalDataStoreSlot AllocateNamedDataSlot (string name) {
+                       lock (datastore_lock) {
                                if (datastorehash == null)
                                        InitDataStoreHash ();
-                               LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash[name];
-                               if(slot!=null) {
+                               LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
+                               if (slot != null) {
                                        // This exception isnt documented (of
                                        // course) but .net throws it
                                        throw new ArgumentException("Named data slot already added");
                                }
                        
-                               slot = new LocalDataStoreSlot();
+                               slot = AllocateDataSlot ();
 
-                               datastorehash.Add(name, slot);
+                               datastorehash.Add (name, slot);
 
-                               return(slot);
+                               return slot;
                        }
                }
 
-               public static void FreeNamedDataSlot(string name) {
-                       lock (typeof (Thread)) {
+               public static void FreeNamedDataSlot (string name) {
+                       lock (datastore_lock) {
                                if (datastorehash == null)
                                        InitDataStoreHash ();
-                               LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
+                               LocalDataStoreSlot slot = (LocalDataStoreSlot)datastorehash [name];
 
-                               if(slot!=null) {
-                                       datastorehash.Remove(slot);
+                               if (slot != null) {
+                                       datastorehash.Remove (slot);
                                }
                        }
                }
 
-               public static object GetData(LocalDataStoreSlot slot) {
-                       Hashtable slothash=GetTLSSlotHash();
-                       return(slothash[slot]);
+               public static LocalDataStoreSlot AllocateDataSlot () {
+                       return new LocalDataStoreSlot (true);
+               }
+
+               public static object GetData (LocalDataStoreSlot slot) {
+                       object[] slots = local_slots;
+                       if (slot == null)
+                               throw new ArgumentNullException ("slot");
+                       if (slots != null && slot.slot < slots.Length)
+                               return slots [slot.slot];
+                       return null;
+               }
+
+               public static void SetData (LocalDataStoreSlot slot, object data) {
+                       object[] slots = local_slots;
+                       if (slot == null)
+                               throw new ArgumentNullException ("slot");
+                       if (slots == null) {
+                               slots = new object [slot.slot + 2];
+                               local_slots = slots;
+                       } else if (slot.slot >= slots.Length) {
+                               object[] nslots = new object [slot.slot + 2];
+                               slots.CopyTo (nslots, 0);
+                               slots = nslots;
+                               local_slots = slots;
+                       }
+                       slots [slot.slot] = data;
                }
 
                public static AppDomain GetDomain() {
@@ -206,36 +242,30 @@ namespace System.Threading
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern static int GetDomainID();
 
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               internal extern static void FreeLocalSlotValues (int slot, bool thread_local);
+
                public static LocalDataStoreSlot GetNamedDataSlot(string name) {
-                       if (datastorehash == null)
-                               InitDataStoreHash ();
-                       LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
+                       lock (datastore_lock) {
+                               if (datastorehash == null)
+                                       InitDataStoreHash ();
+                               LocalDataStoreSlot slot=(LocalDataStoreSlot)datastorehash[name];
 
-                       if(slot==null) {
-                               slot=AllocateNamedDataSlot(name);
-                       }
+                               if(slot==null) {
+                                       slot=AllocateNamedDataSlot(name);
+                               }
                        
-                       return(slot);
+                               return(slot);
+                       }
                }
                
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static void ResetAbort_internal();
 
-               public static void ResetAbort()
+               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
+               public static void ResetAbort ()
                {
-                       ResetAbort_internal();
-               }
-               
-
-               public static void SetData(LocalDataStoreSlot slot,
-                                          object data) {
-                       Hashtable slothash=GetTLSSlotHash();
-
-                       if(slothash.Contains(slot)) {
-                               slothash.Remove(slot);
-                       }
-                       
-                       slothash.Add(slot, data);
+                       ResetAbort_internal ();
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -245,12 +275,7 @@ namespace System.Threading
                        if((millisecondsTimeout<0) && (millisecondsTimeout != Timeout.Infinite)) {
                                throw new ArgumentException("Negative timeout");
                        }
-                       Thread thread=CurrentThread;
-                               
-                       thread.set_state(ThreadState.WaitSleepJoin);
-                               
                        Sleep_internal(millisecondsTimeout);
-                       thread.clr_state(ThreadState.WaitSleepJoin);
                }
 
                public static void Sleep(TimeSpan timeout) {
@@ -261,16 +286,12 @@ namespace System.Threading
                                throw new ArgumentOutOfRangeException("Timeout out of range");
                        }
 
-                       Thread thread=CurrentThread;
-                               
-                       thread.set_state(ThreadState.WaitSleepJoin);
                        Sleep_internal(ms);
-                       thread.clr_state(ThreadState.WaitSleepJoin);
                }
 
                // Returns the system thread handle
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern IntPtr Thread_internal(ThreadStart start);
+               private extern IntPtr Thread_internal (MulticastDelegate start);
 
                public Thread(ThreadStart start) {
                        if(start==null) {
@@ -280,6 +301,9 @@ namespace System.Threading
                }
 
                [MonoTODO]
+#if NET_2_0
+               [Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
+#endif
                public ApartmentState ApartmentState {
                        get {
                                return(ApartmentState.Unknown);
@@ -292,6 +316,30 @@ namespace System.Threading
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                private static extern int current_lcid ();
 
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern CultureInfo GetCachedCurrentCulture ();
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern byte[] GetSerializedCurrentCulture ();
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern void SetCachedCurrentCulture (CultureInfo culture);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern void SetSerializedCurrentCulture (byte[] culture);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern CultureInfo GetCachedCurrentUICulture ();
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern byte[] GetSerializedCurrentUICulture ();
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern void SetCachedCurrentUICulture (CultureInfo culture);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               private extern void SetSerializedCurrentUICulture (byte[] culture);
+
                /* If the current_lcid() isn't known by CultureInfo,
                 * it will throw an exception which may cause
                 * String.Concat to try and recursively look up the
@@ -299,55 +347,147 @@ namespace System.Threading
                 * Use a boolean to short-circuit this scenario.
                 */
                private static bool in_currentculture=false;
+
+               static object culture_lock = new object ();
                
+               /*
+                * Thread objects are shared between appdomains, and CurrentCulture
+                * should always return an object in the calling appdomain. See bug
+                * http://bugzilla.ximian.com/show_bug.cgi?id=50049 for more info.
+                * This is hard to implement correctly and efficiently, so the current
+                * implementation is not perfect: changes made in one appdomain to the 
+                * state of the current cultureinfo object are not visible to other 
+                * appdomains.
+                */             
                public CultureInfo CurrentCulture {
                        get {
-                               if (current_culture == null) {
-                                       lock (typeof (Thread)) {
-                                               if(current_culture==null) {
-                                                       if(in_currentculture==true) {
-                                                               /* Bail out */
-                                                               current_culture = CultureInfo.InvariantCulture;
-                                                       } else {
-                                                               in_currentculture=true;
-                                                       
-                                                               current_culture = CultureInfo.ConstructCurrentCulture ();
-                                                       }
-                                               }
-                                               
-                                               in_currentculture=false;
+                               if (in_currentculture)
+                                       /* Bail out */
+                                       return CultureInfo.InvariantCulture;
+
+                               CultureInfo culture = GetCachedCurrentCulture ();
+                               if (culture != null)
+                                       return culture;
+
+                               byte[] arr = GetSerializedCurrentCulture ();
+                               if (arr == null) {
+                                       lock (culture_lock) {
+                                               in_currentculture=true;
+                                               culture = CultureInfo.ConstructCurrentCulture ();
+                                               //
+                                               // Don't serialize the culture in this case to avoid
+                                               // initializing the serialization infrastructure in the
+                                               // common case when the culture is not set explicitly.
+                                               //
+                                               SetCachedCurrentCulture (culture);
+                                               in_currentculture = false;
+                                               return culture;
                                        }
                                }
-                               
-                               return(current_culture);
+
+                               /*
+                                * No cultureinfo object exists for this domain, so create one
+                                * by deserializing the serialized form.
+                                */
+                               in_currentculture = true;
+                               try {
+                                       BinaryFormatter bf = new BinaryFormatter ();
+                                       MemoryStream ms = new MemoryStream (arr);
+                                       culture = (CultureInfo)bf.Deserialize (ms);
+                                       SetCachedCurrentCulture (culture);
+                               } finally {
+                                       in_currentculture = false;
+                               }
+
+                               return culture;
                        }
                        
+                       [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
                        set {
-                               current_culture = value;
+                               if (value == null)
+                                       throw new ArgumentNullException ("value");
+
+                               value.CheckNeutral ();
+                               in_currentculture = true;
+                               try {
+                                       BinaryFormatter bf = new BinaryFormatter();
+                                       MemoryStream ms = new MemoryStream ();
+                                       bf.Serialize (ms, value);
+
+                                       SetCachedCurrentCulture (value);
+                                       SetSerializedCurrentCulture (ms.GetBuffer ());
+                               } finally {
+                                       in_currentculture = false;
+                               }
                        }
                }
 
                public CultureInfo CurrentUICulture {
                        get {
-                               if (current_ui_culture == null) {
-                                       lock (this) {
-                                               if(current_ui_culture==null) {
-                                                       /* We don't
-                                                        * distinguish
-                                                        * between
-                                                        * System and
-                                                        * UI cultures
-                                                        */
-                                                       current_ui_culture = CultureInfo.ConstructCurrentUICulture ();
-                                               }
+                               if (in_currentculture)
+                                       /* Bail out */
+                                       return CultureInfo.InvariantCulture;
+
+                               CultureInfo culture = GetCachedCurrentUICulture ();
+                               if (culture != null)
+                                       return culture;
+
+                               byte[] arr = GetSerializedCurrentUICulture ();
+                               if (arr == null) {
+                                       lock (culture_lock) {
+                                               in_currentculture=true;
+                                               /* We don't
+                                                * distinguish
+                                                * between
+                                                * System and
+                                                * UI cultures
+                                                */
+                                               culture = CultureInfo.ConstructCurrentUICulture ();
+                                               //
+                                               // Don't serialize the culture in this case to avoid
+                                               // initializing the serialization infrastructure in the
+                                               // common case when the culture is not set explicitly.
+                                               //
+                                               SetCachedCurrentUICulture (culture);
+                                               in_currentculture = false;
+                                               return culture;
                                        }
                                }
-                               
-                               return(current_ui_culture);
+
+                               /*
+                                * No cultureinfo object exists for this domain, so create one
+                                * by deserializing the serialized form.
+                                */
+                               in_currentculture = true;
+                               try {
+                                       BinaryFormatter bf = new BinaryFormatter ();
+                                       MemoryStream ms = new MemoryStream (arr);
+                                       culture = (CultureInfo)bf.Deserialize (ms);
+                                       SetCachedCurrentUICulture (culture);
+                               }
+                               finally {
+                                       in_currentculture = false;
+                               }
+
+                               return culture;
                        }
                        
                        set {
-                               current_ui_culture = value;
+                               in_currentculture = true;
+                               
+                               if (value == null)
+                                       throw new ArgumentNullException ("value");
+
+                               try {
+                                       BinaryFormatter bf = new BinaryFormatter();
+                                       MemoryStream ms = new MemoryStream ();
+                                       bf.Serialize (ms, value);
+
+                                       SetCachedCurrentUICulture (value);
+                                       SetSerializedCurrentUICulture (ms.GetBuffer ());
+                               } finally {
+                                       in_currentculture = false;
+                               }
                        }
                }
 
@@ -368,7 +508,7 @@ namespace System.Threading
 
                public bool IsAlive {
                        get {
-                               ThreadState curstate=state;
+                               ThreadState curstate = GetState ();
                                
                                if((curstate & ThreadState.Aborted) != 0 ||
                                   (curstate & ThreadState.Stopped) != 0 ||
@@ -382,18 +522,14 @@ namespace System.Threading
 
                public bool IsBackground {
                        get {
-                               if((state & ThreadState.Background) != 0) {
-                                       return(true);
-                               } else {
-                                       return(false);
-                               }
+                               return (GetState () & ThreadState.Background) != 0;
                        }
                        
                        set {
-                               if(value==true) {
-                                       set_state(ThreadState.Background);
+                               if (value) {
+                                       SetState (ThreadState.Background);
                                } else {
-                                       clr_state(ThreadState.Background);
+                                       ClrState (ThreadState.Background);
                                }
                        }
                }
@@ -415,13 +551,7 @@ namespace System.Threading
                        }
                        
                        set {
-                               lock (this) {
-                                       if(Name!=null) {
-                                               throw new InvalidOperationException ("Thread.Name can only be set once.");
-                                       }
-                               
-                                       SetName_internal (value);
-                               }
+                               SetName_internal (value);
                        }
                }
 
@@ -437,24 +567,31 @@ namespace System.Threading
 
                public ThreadState ThreadState {
                        get {
-                               return(state);
+                               return GetState ();
                        }
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern void Abort_internal (object stateInfo);
 
-               public void Abort() {
+               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
+               public void Abort () 
+               {
                        Abort_internal (null);
                }
 
-               public void Abort(object stateInfo) {
-                       Abort_internal(stateInfo);
+               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
+               public void Abort (object stateInfo) 
+               {
+                       Abort_internal (stateInfo);
                }
                
 
                [MonoTODO]
-               public void Interrupt() {
+               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
+               public void Interrupt ()
+               {
+                       throw new NotImplementedException ();
                }
 
                // The current thread joins with 'this'. Set ms to 0 to block
@@ -462,120 +599,83 @@ namespace System.Threading
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern bool Join_internal(int ms, IntPtr handle);
                
-               public void Join() {
-                       if((state & ThreadState.Unstarted) != 0) {
-                               throw new ThreadStateException("Thread has not been started");
-                       }
-                       
-                       Thread thread=CurrentThread;
-                               
-                       thread.set_state(ThreadState.WaitSleepJoin);
+               public void Join()
+               {
                        Join_internal(Timeout.Infinite, system_thread_handle);
-                       thread.clr_state(ThreadState.WaitSleepJoin);
                }
 
-               public bool Join(int millisecondsTimeout) {
+               public bool Join(int millisecondsTimeout)
+               {
                        if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
                                throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
 
-                       if((state & ThreadState.Unstarted) != 0) {
-                               throw new ThreadStateException("Thread has not been started");
-                       }
-
-                       Thread thread=CurrentThread;
-                               
-                       thread.set_state(ThreadState.WaitSleepJoin);
-                       bool ret=Join_internal(millisecondsTimeout,
-                                              system_thread_handle);
-                       thread.clr_state(ThreadState.WaitSleepJoin);
-
-                       return(ret);
+                       return Join_internal(millisecondsTimeout, system_thread_handle);
                }
 
-               public bool Join(TimeSpan timeout) {
+               public bool Join(TimeSpan timeout)
+               {
                        // LAMESPEC: says to throw ArgumentException too
                        int ms=Convert.ToInt32(timeout.TotalMilliseconds);
                        
                        if(ms < 0 || ms > Int32.MaxValue) {
                                throw new ArgumentOutOfRangeException("timeout out of range");
                        }
-                       if((state & ThreadState.Unstarted) != 0) {
-                               throw new ThreadStateException("Thread has not been started");
-                       }
-
-                       Thread thread=CurrentThread;
-
-                       thread.set_state(ThreadState.WaitSleepJoin);
-                       bool ret=Join_internal(ms, system_thread_handle);
-                       thread.clr_state(ThreadState.WaitSleepJoin);
-
-                       return(ret);
+                       return Join_internal(ms, system_thread_handle);
                }
 
 #if NET_1_1
-               [MonoTODO ("seems required for multi-processors systems like Itanium")]
-               public static void MemoryBarrier ()
-               {
-                       throw new NotImplementedException ();
-               }
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               public extern static void MemoryBarrier ();
 #endif
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern void Resume_internal();
 
+#if NET_2_0
+               [Obsolete ("")]
+#endif
+               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
                public void Resume () 
                {
-                       if ((state & ThreadState.Unstarted) != 0 || !IsAlive || 
-                               ((state & ThreadState.Suspended) == 0 && (state & ThreadState.SuspendRequested) == 0)) 
-                       {
-                               throw new ThreadStateException("Thread has not been started, or is dead");
-                       }
-                       
                        Resume_internal ();
                }
 
                [MonoTODO]
+#if NET_2_0
+               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
+#endif
                public static void SpinWait (int iterations) 
                {
                        throw new NotImplementedException ();
                }
 
-               // Launches the thread
-               [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private extern void Start_internal(IntPtr handle);
-               
                public void Start() {
-                       lock(this) {
-                               if((state & ThreadState.Unstarted) == 0) {
-                                       throw new ThreadStateException("Thread has already been started");
-                               }
-                               
-
-                               // Thread_internal creates the new thread, but
-                               // blocks it until Start() is called later.
-                               system_thread_handle=Thread_internal(threadstart);
-
-                               if (system_thread_handle == (IntPtr) 0) {
-                                       throw new SystemException ("Thread creation failed");
-                               }
-
-                               // Launch this thread
-                               Start_internal(system_thread_handle);
+                       // propagate informations from the original thread to the new thread
+#if NET_2_0
+                       if (!ExecutionContext.IsFlowSuppressed ())
+                               _ec = ExecutionContext.Capture ();
+#else
+                       // before 2.0 this was only used for security (mostly CAS) so we
+                       // do this only if the security manager is active
+                       if (SecurityManager.SecurityEnabled)
+                               _ec = ExecutionContext.Capture ();
+#endif
+                       if (CurrentThread._principal != null)
+                               _principal = CurrentThread._principal;
 
-                               // Mark the thread state as Running
-                               // (which is all bits
-                               // cleared). Therefore just remove the
-                               // Unstarted bit
-                               clr_state(ThreadState.Unstarted);
-                       }
+                       // Thread_internal creates and starts the new thread, 
+                       if (Thread_internal(threadstart) == (IntPtr) 0)
+                               throw new SystemException ("Thread creation failed.");
                }
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern void Suspend_internal();
 
-               public void Suspend() {
-                       if((state & ThreadState.Unstarted) != 0 || !IsAlive) {
-                               throw new ThreadStateException("Thread has not been started, or is dead");
-                       }
+#if NET_2_0
+               [Obsolete ("")]
+#endif
+               [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
+               public void Suspend ()
+               {
                        Suspend_internal ();
                }
 
@@ -583,22 +683,23 @@ namespace System.Threading
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern void Thread_free_internal(IntPtr handle);
 
+#if NET_2_0
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
+#endif
                ~Thread() {
                        // Free up the handle
                        if (system_thread_handle != (IntPtr) 0)
                                Thread_free_internal(system_thread_handle);
                }
 
-               private void set_state(ThreadState set) {
-                       lock(this) {
-                               state |= set;
-                       }
-               }
-               private void clr_state(ThreadState clr) {
-                       lock(this) {
-                               state &= ~clr;
-                       }
-               }
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               extern private void SetState (ThreadState set);
+               
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               extern private void ClrState (ThreadState clr);
+               
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               extern private ThreadState GetState ();
 
 #if NET_1_1
                
@@ -644,7 +745,7 @@ namespace System.Threading
 
                [CLSCompliant (false)]
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern public static byte VolatileRead (ref UIntPtr address);
+               extern public static UIntPtr VolatileRead (ref UIntPtr address);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                extern public static void VolatileWrite (ref byte address, byte value);
@@ -691,6 +792,201 @@ namespace System.Threading
                extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
                
 #endif
+
+#if NET_2_0
+               public Thread (ThreadStart start, int maxStackSize)
+               {
+                       if (start == null)
+                               throw new ArgumentNullException ("start");
+                       if (maxStackSize < 131072)
+                               throw new ArgumentException ("< 128 kb", "maxStackSize");
+
+                       threadstart = start;
+                       stack_size = maxStackSize;
+               }
+
+               public Thread (ParameterizedThreadStart start)
+               {
+                       if (start == null)
+                               throw new ArgumentNullException ("start");
+
+                       threadstart = start;
+               }
+
+               public Thread (ParameterizedThreadStart start, int maxStackSize)
+               {
+                       if (start == null)
+                               throw new ArgumentNullException ("start");
+                       if (maxStackSize < 131072)
+                               throw new ArgumentException ("< 128 kb", "maxStackSize");
+
+                       threadstart = start;
+                       stack_size = maxStackSize;
+               }
+
+               [MonoTODO ("limited to CompressedStack support")]
+               public ExecutionContext ExecutionContext {
+                       [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
+                       get {
+                               if (_ec == null)
+                                       _ec = new ExecutionContext ();
+                               return _ec;
+                       }
+               }
+
+               public int ManagedThreadId {
+               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
+                       get { return (int)thread_id; }
+               }
+
+               [MonoTODO]
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
+               public static void BeginCriticalRegion ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
+               public static void EndCriticalRegion ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
+               public static void BeginThreadAffinity ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
+               public static void EndThreadAffinity ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               //
+               // We disable warning 618, because we are accessing the
+               // empty property ApartmentState which produces an Obsolete
+               // message, but since its an empty routine needed for 1.x
+               // we use it.
+               //
+               // Maybe we should later turn these into internal methods for 1.x
+               // instead and have the property call these.
+               
+               
+               [MonoTODO]
+               public ApartmentState GetApartmentState ()
+               {
+                       return this.ApartmentState;
+               }
+
+               [MonoTODO]
+               public void SetApartmentState (ApartmentState state)
+               {
+                       this.ApartmentState = state;
+               }
+
+               [MonoTODO]
+               public bool TrySetApartmentState (ApartmentState state)
+               {
+                       try {
+                               this.ApartmentState = state;
+                               return true;
+                       }
+                       catch (ArgumentException) {
+                               throw;
+                       }
+                       catch {
+                               return false;
+                       }
+               }
                
+               [ComVisible (false)]
+               public override int GetHashCode ()
+               {
+                       // ??? overridden but not guaranteed to be unique ???
+                       return (int)thread_id;
+               }
+
+               public void Start (object parameter)
+               {
+                       start_obj = parameter;
+                       Start ();
+               }
+#else
+               internal ExecutionContext ExecutionContext {
+                       get {
+                               if (_ec == null)
+                                       _ec = new ExecutionContext ();
+                               return _ec;
+                       }
+               }
+#endif
+
+               // NOTE: This method doesn't show in the class library status page because
+               // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
+               // But it's there!
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+               [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
+#if NET_2_0
+               [Obsolete ("see CompressedStack class")]
+#endif
+#if NET_1_1
+               public
+#else
+               internal
+#endif
+               CompressedStack GetCompressedStack ()
+               {
+                       // Note: returns null if no CompressedStack has been set.
+                       // However CompressedStack.GetCompressedStack returns an 
+                       // (empty?) CompressedStack instance.
+                       CompressedStack cs = ExecutionContext.SecurityContext.CompressedStack;
+                       return ((cs == null) || cs.IsEmpty ()) ? null : cs.CreateCopy ();
+               }
+
+               // NOTE: This method doesn't show in the class library status page because
+               // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
+               // But it's there!
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true)]
+               [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey="00000000000000000400000000000000")]
+#if NET_2_0
+               [Obsolete ("see CompressedStack class")]
+#endif
+#if NET_1_1
+               public
+#else
+               internal
+#endif
+               void SetCompressedStack (CompressedStack stack)
+               {
+                       ExecutionContext.SecurityContext.CompressedStack = stack;
+               }
+
+#if NET_1_1
+               void _Thread.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void _Thread.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void _Thread.GetTypeInfoCount (out uint pcTInfo)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               void _Thread.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
+                       IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
        }
 }