using System.Runtime.InteropServices;
using System.IO;
using System.Collections;
+using System.Reflection;
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
-
+ internal class InternalThread : CriticalFinalizerObject {
+#pragma warning disable 169, 414, 649
#region Sync with metadata/object-internals.h
int lock_thread_id;
// stores a thread handle
- private IntPtr system_thread_handle;
+ internal IntPtr system_thread_handle;
/* Note this is an opaque object (an array), not a CultureInfo */
private object cached_culture_info;
private IntPtr unused0;
- private bool threadpool_thread;
+ internal bool threadpool_thread;
/* accessed only from unmanaged code */
private IntPtr name;
private int name_len;
- private ThreadState state = ThreadState.Unstarted;
+ private ThreadState state;
private object abort_exc;
- internal object abort_state;
+ private int abort_state_handle;
/* thread_id is only accessed from unmanaged code */
- private Int64 thread_id;
+ internal Int64 thread_id;
/* start_notify is used by the runtime to signal that Start()
* is ok to return
private UIntPtr static_data; /* GC-tracked */
private IntPtr jit_data;
private IntPtr lock_data;
- Context current_appcontext;
- int stack_size;
- object start_obj;
+ /* current System.Runtime.Remoting.Contexts.Context instance
+ keep as an object to avoid triggering its class constructor when not needed */
+ private object current_appcontext;
+ internal int stack_size;
private IntPtr appdomain_refs;
- private bool interruption_requested;
+ private int interruption_requested;
private IntPtr suspend_event;
private IntPtr suspended_event;
private IntPtr resume_event;
- /* Don't lock on synch_cs in managed code, since it can result in deadlocks */
- private object synch_cs = null;
- 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;
+ private IntPtr synch_cs;
private bool thread_dump_requested;
private IntPtr end_stack;
private bool thread_interrupt_requested;
- private byte apartment_state = (byte)ApartmentState.Unknown;
+ internal byte apartment_state;
+ internal volatile int critical_region_level;
+ private int small_id;
+ private IntPtr manage_callback;
+ private object pending_exception;
+ /* This is the ExecutionContext that will be set by
+ start_wrapper() in the runtime. */
+ private ExecutionContext ec_to_set;
+
+ private IntPtr interrupt_on_stop;
+
/*
* These fields are used to avoid having to increment corlib versions
* when a new field is added to the unmanaged MonoThread structure.
*/
+ private IntPtr unused3;
+ private IntPtr unused4;
private IntPtr unused5;
private IntPtr unused6;
- private IntPtr unused7;
#endregion
+#pragma warning restore 169, 414, 649
+
+ internal int managed_id;
+
+ internal byte[] _serialized_principal;
+ internal int _serialized_principal_version;
- // the name of local_slots is important as it's used by the runtime.
- [ThreadStatic]
+ internal byte[] serialized_culture_info;
+ internal byte[] serialized_ui_culture_info;
+
+ /* 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
+ * CurrentCulture, which will throw an exception, etc.
+ * Use a boolean to short-circuit this scenario.
+ */
+ internal bool in_currentculture=false;
+
+ // Closes the system thread handle
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void Thread_free_internal(IntPtr handle);
+
+ [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
+ ~InternalThread() {
+ Thread_free_internal(system_thread_handle);
+ }
+ }
+
+ [ClassInterface (ClassInterfaceType.None)]
+ [ComVisible (true)]
+ [ComDefaultInterface (typeof (_Thread))]
+ public sealed class Thread : CriticalFinalizerObject, _Thread {
+#pragma warning disable 414
+ #region Sync with metadata/object-internals.h
+ private InternalThread internal_thread;
+ object start_obj;
+ private ExecutionContext ec_to_set;
+ #endregion
+#pragma warning restore 414
+
+ IPrincipal principal;
+ int principal_version;
+
+ // the name of local_slots, current_thread and _ec is
+ // important because they are used by the runtime.
+ [ThreadStatic]
static object[] local_slots;
- // can be both a ThreadSart and a ParameterizedThreadStart
+ [ThreadStatic]
+ static Thread current_thread;
+
+ /* The actual ExecutionContext of the thread. It's
+ ThreadStatic so that it's not shared between
+ AppDomains. */
+ [ThreadStatic]
+ static ExecutionContext _ec;
+
+ // can be both a ThreadStart and a ParameterizedThreadStart
private MulticastDelegate threadstart;
- private string thread_name=null;
-
- private IPrincipal _principal;
+ //private string thread_name=null;
+
+ private static int _managed_id_counter;
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void ConstructInternalThread ();
+
+ private InternalThread Internal {
+ get {
+ if (internal_thread == null)
+ ConstructInternalThread ();
+ return internal_thread;
+ }
+ }
public static Context CurrentContext {
[SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
}
}
+ /*
+ * These two methods return an array in the target
+ * domain with the same content as the argument. If
+ * the argument is already in the target domain, then
+ * the argument is returned, otherwise a copy.
+ */
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static byte[] ByteArrayToRootDomain (byte[] arr);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
+
+#if !MOONLIGHT
public static IPrincipal CurrentPrincipal {
get {
- IPrincipal p = null;
Thread th = CurrentThread;
- lock (th) {
- p = th._principal;
- if (p == null) {
- p = GetDomain ().DefaultPrincipal;
- th._principal = p;
+
+ if (th.principal_version != th.Internal._serialized_principal_version)
+ th.principal = null;
+
+ if (th.principal != null)
+ return th.principal;
+
+ if (th.Internal._serialized_principal != null) {
+ try {
+ BinaryFormatter bf = new BinaryFormatter ();
+ MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
+ th.principal = (IPrincipal) bf.Deserialize (ms);
+ th.principal_version = th.Internal._serialized_principal_version;
+ return th.principal;
+ } catch (Exception) {
}
}
- return p;
+
+ th.principal = GetDomain ().DefaultPrincipal;
+ th.principal_version = th.Internal._serialized_principal_version;
+ return th.principal;
}
[SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
set {
- CurrentThread._principal = value;
+ Thread th = CurrentThread;
+
+ ++th.Internal._serialized_principal_version;
+ try {
+ BinaryFormatter bf = new BinaryFormatter ();
+ MemoryStream ms = new MemoryStream ();
+ bf.Serialize (ms, value);
+ th.Internal._serialized_principal = ByteArrayToRootDomain (ms.ToArray ());
+ } catch (Exception) {
+ th.Internal._serialized_principal = null;
+ }
+
+ th.principal = value;
+ th.principal_version = th.Internal._serialized_principal_version;
}
}
+#endif
// Looks up the object associated with the current thread
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern static Thread CurrentThread_internal();
-
+ private extern static InternalThread CurrentInternalThread_internal();
+
public static Thread CurrentThread {
-#if NET_2_0
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
-#endif
get {
- return(CurrentThread_internal());
+ if (current_thread == null)
+ current_thread = new Thread (CurrentInternalThread_internal ());
+ return current_thread;
}
}
internal static int CurrentThreadId {
get {
- return (int)(CurrentThread.thread_id);
+ return (int)(CurrentThread.internal_thread.thread_id);
}
}
+#if !MOONLIGHT
// Stores a hash keyed by strings of LocalDataStoreSlot objects
static Hashtable datastorehash;
private static object datastore_lock = new object ();
slots [slot.slot] = data;
}
- public static AppDomain GetDomain() {
- return AppDomain.CurrentDomain;
- }
-
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
- public extern static int GetDomainID();
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal extern static void FreeLocalSlotValues (int slot, bool thread_local);
return(slot);
}
}
+#endif
+ public static AppDomain GetDomain() {
+ return AppDomain.CurrentDomain;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern static int GetDomainID();
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void ResetAbort_internal();
ResetAbort_internal ();
}
+#if NET_4_0 || BOOTSTRAP_NET_4_0
+ [HostProtectionAttribute (SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern static bool Yield ();
+#endif
+
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void Sleep_internal(int ms);
- public static void Sleep(int millisecondsTimeout) {
- if((millisecondsTimeout<0) && (millisecondsTimeout != Timeout.Infinite)) {
- throw new ArgumentException("Negative timeout");
- }
- Sleep_internal(millisecondsTimeout);
+ public static void Sleep (int millisecondsTimeout)
+ {
+ if (millisecondsTimeout < Timeout.Infinite)
+ throw new ArgumentOutOfRangeException ("millisecondsTimeout", "Negative timeout");
+
+ Sleep_internal (millisecondsTimeout);
}
- public static void Sleep(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");
- }
+ public static void Sleep (TimeSpan timeout)
+ {
+ long ms = (long) timeout.TotalMilliseconds;
+ if (ms < Timeout.Infinite || ms > Int32.MaxValue)
+ throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
- Sleep_internal(ms);
+ Sleep_internal ((int) ms);
}
// Returns the system thread handle
threadstart=start;
}
-#if NET_2_0
+ private Thread (InternalThread it) {
+ internal_thread = it;
+ }
+
+#if !MOONLIGHT
[Obsolete ("Deprecated in favor of GetApartmentState, SetApartmentState and TrySetApartmentState.")]
-#endif
public ApartmentState ApartmentState {
get {
if ((ThreadState & ThreadState.Stopped) != 0)
throw new ThreadStateException ("Thread is dead; state can not be accessed.");
- return (ApartmentState)apartment_state;
+ return (ApartmentState)Internal.apartment_state;
}
- set {
-#if NET_2_0
+ set {
TrySetApartmentState (value);
-#else
- if ((ThreadState & ThreadState.Unstarted) == 0)
- throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
-
- if (value != ApartmentState.STA && value != ApartmentState.MTA)
- throw new ArgumentException ("value is not a valid apartment state.");
-
- if ((ApartmentState)apartment_state == ApartmentState.Unknown)
- apartment_state = (byte)value;
-#endif
}
}
+#endif // !NET_2_1
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private static extern int current_lcid ();
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern CultureInfo GetCachedCurrentCulture ();
+ //[MethodImplAttribute (MethodImplOptions.InternalCall)]
+ //private static extern int current_lcid ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern byte[] GetSerializedCurrentCulture ();
+ private extern static CultureInfo GetCachedCurrentCulture (InternalThread thread);
[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 ();
+ private extern static CultureInfo GetCachedCurrentUICulture (InternalThread thread);
[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
- * CurrentCulture, which will throw an exception, etc.
- * Use a boolean to short-circuit this scenario.
- */
- private static bool in_currentculture=false;
-
+ /* FIXME: in_currentculture exists once, but
+ culture_lock is once per appdomain. Is it correct
+ to lock this way? */
static object culture_lock = new object ();
/*
*/
public CultureInfo CurrentCulture {
get {
- if (in_currentculture)
+ if (Internal.in_currentculture)
/* Bail out */
return CultureInfo.InvariantCulture;
- CultureInfo culture = GetCachedCurrentCulture ();
+ CultureInfo culture = GetCachedCurrentCulture (Internal);
if (culture != null)
return culture;
- byte[] arr = GetSerializedCurrentCulture ();
+ byte[] arr = ByteArrayToCurrentDomain (Internal.serialized_culture_info);
if (arr == null) {
lock (culture_lock) {
- in_currentculture=true;
+ Internal.in_currentculture=true;
culture = CultureInfo.ConstructCurrentCulture ();
//
// Don't serialize the culture in this case to avoid
// common case when the culture is not set explicitly.
//
SetCachedCurrentCulture (culture);
- in_currentculture = false;
+ Internal.in_currentculture = false;
+ NumberFormatter.SetThreadCurrentCulture (culture);
return culture;
}
}
* No cultureinfo object exists for this domain, so create one
* by deserializing the serialized form.
*/
- in_currentculture = true;
+ Internal.in_currentculture = true;
try {
BinaryFormatter bf = new BinaryFormatter ();
MemoryStream ms = new MemoryStream (arr);
culture = (CultureInfo)bf.Deserialize (ms);
SetCachedCurrentCulture (culture);
} finally {
- in_currentculture = false;
+ Internal.in_currentculture = false;
}
+ NumberFormatter.SetThreadCurrentCulture (culture);
return culture;
}
if (value == null)
throw new ArgumentNullException ("value");
+ CultureInfo culture = GetCachedCurrentCulture (Internal);
+ if (culture == value)
+ return;
+
value.CheckNeutral ();
- in_currentculture = true;
+ Internal.in_currentculture = true;
try {
- BinaryFormatter bf = new BinaryFormatter();
- MemoryStream ms = new MemoryStream ();
- bf.Serialize (ms, value);
-
SetCachedCurrentCulture (value);
- SetSerializedCurrentCulture (ms.GetBuffer ());
+
+ byte[] serialized_form = null;
+
+ if (value.IsReadOnly && value.cached_serialized_form != null) {
+ serialized_form = value.cached_serialized_form;
+ } else {
+ BinaryFormatter bf = new BinaryFormatter();
+ MemoryStream ms = new MemoryStream ();
+ bf.Serialize (ms, value);
+
+ serialized_form = ms.GetBuffer ();
+ if (value.IsReadOnly)
+ value.cached_serialized_form = serialized_form;
+ }
+
+ Internal.serialized_culture_info = ByteArrayToRootDomain (serialized_form);
} finally {
- in_currentculture = false;
+ Internal.in_currentculture = false;
}
+ NumberFormatter.SetThreadCurrentCulture (value);
}
}
public CultureInfo CurrentUICulture {
get {
- if (in_currentculture)
+ if (Internal.in_currentculture)
/* Bail out */
return CultureInfo.InvariantCulture;
- CultureInfo culture = GetCachedCurrentUICulture ();
+ CultureInfo culture = GetCachedCurrentUICulture (Internal);
if (culture != null)
return culture;
- byte[] arr = GetSerializedCurrentUICulture ();
+ byte[] arr = ByteArrayToCurrentDomain (Internal.serialized_ui_culture_info);
if (arr == null) {
lock (culture_lock) {
- in_currentculture=true;
+ Internal.in_currentculture=true;
/* We don't
* distinguish
* between
// common case when the culture is not set explicitly.
//
SetCachedCurrentUICulture (culture);
- in_currentculture = false;
+ Internal.in_currentculture = false;
return culture;
}
}
* No cultureinfo object exists for this domain, so create one
* by deserializing the serialized form.
*/
- in_currentculture = true;
+ Internal.in_currentculture = true;
try {
BinaryFormatter bf = new BinaryFormatter ();
MemoryStream ms = new MemoryStream (arr);
SetCachedCurrentUICulture (culture);
}
finally {
- in_currentculture = false;
+ Internal.in_currentculture = false;
}
return culture;
}
set {
- in_currentculture = true;
-
if (value == null)
throw new ArgumentNullException ("value");
- try {
- BinaryFormatter bf = new BinaryFormatter();
- MemoryStream ms = new MemoryStream ();
- bf.Serialize (ms, value);
+ CultureInfo culture = GetCachedCurrentUICulture (Internal);
+ if (culture == value)
+ return;
+ Internal.in_currentculture = true;
+ try {
SetCachedCurrentUICulture (value);
- SetSerializedCurrentUICulture (ms.GetBuffer ());
+
+ byte[] serialized_form = null;
+
+ if (value.IsReadOnly && value.cached_serialized_form != null) {
+ serialized_form = value.cached_serialized_form;
+ } else {
+ BinaryFormatter bf = new BinaryFormatter();
+ MemoryStream ms = new MemoryStream ();
+ bf.Serialize (ms, value);
+
+ serialized_form = ms.GetBuffer ();
+ if (value.IsReadOnly)
+ value.cached_serialized_form = serialized_form;
+ }
+
+ Internal.serialized_ui_culture_info = ByteArrayToRootDomain (serialized_form);
} finally {
- in_currentculture = false;
+ Internal.in_currentculture = false;
}
}
}
internal bool IsThreadPoolThreadInternal {
get {
- return threadpool_thread;
+ return Internal.threadpool_thread;
}
set {
- threadpool_thread = value;
+ Internal.threadpool_thread = value;
}
}
public bool IsAlive {
get {
- ThreadState curstate = GetState ();
+ ThreadState curstate = GetState (Internal);
if((curstate & ThreadState.Aborted) != 0 ||
(curstate & ThreadState.Stopped) != 0 ||
public bool IsBackground {
get {
- ThreadState thread_state = GetState ();
+ ThreadState thread_state = GetState (Internal);
if ((thread_state & ThreadState.Stopped) != 0)
throw new ThreadStateException ("Thread is dead; state can not be accessed.");
set {
if (value) {
- SetState (ThreadState.Background);
+ SetState (Internal, ThreadState.Background);
} else {
- ClrState (ThreadState.Background);
+ ClrState (Internal, ThreadState.Background);
}
}
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern string GetName_internal ();
+ private extern static string GetName_internal (InternalThread thread);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern void SetName_internal (String name);
+ private extern static void SetName_internal (InternalThread thread, String name);
/*
* The thread name must be shared by appdomains, so it is stored in
public string Name {
get {
- return GetName_internal ();
+ return GetName_internal (Internal);
}
set {
- SetName_internal (value);
+ SetName_internal (Internal, value);
}
}
+#if !MOONLIGHT
public ThreadPriority Priority {
get {
return(ThreadPriority.Lowest);
// FIXME: Implement setter.
}
}
+#endif
public ThreadState ThreadState {
get {
- return GetState ();
+ return GetState (Internal);
}
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern void Abort_internal (object stateInfo);
+ private extern static void Abort_internal (InternalThread thread, object stateInfo);
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
public void Abort ()
{
- Abort_internal (null);
+ Abort_internal (Internal, null);
}
+#if !MOONLIGHT
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
public void Abort (object stateInfo)
{
- Abort_internal (stateInfo);
+ Abort_internal (Internal, stateInfo);
}
-
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern object GetAbortExceptionState ();
+
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern void Interrupt_internal ();
+ private extern static void Interrupt_internal (InternalThread thread);
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
public void Interrupt ()
{
- Interrupt_internal ();
+ Interrupt_internal (Internal);
}
+#endif
// The current thread joins with 'this'. Set ms to 0 to block
// until this actually exits.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern bool Join_internal(int ms, IntPtr handle);
+ private extern static bool Join_internal(InternalThread thread, int ms, IntPtr handle);
public void Join()
{
- Join_internal(Timeout.Infinite, system_thread_handle);
+ Join_internal(Internal, Timeout.Infinite, Internal.system_thread_handle);
}
public bool Join(int millisecondsTimeout)
{
- if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout < 0)
- throw new ArgumentException ("Timeout less than zero", "millisecondsTimeout");
+ if (millisecondsTimeout < Timeout.Infinite)
+ throw new ArgumentOutOfRangeException ("millisecondsTimeout", "Timeout less than zero");
- return Join_internal(millisecondsTimeout, system_thread_handle);
+ return Join_internal (Internal, millisecondsTimeout, Internal.system_thread_handle);
}
+#if !MOONLIGHT
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");
- }
- return Join_internal(ms, system_thread_handle);
+ long ms = (long) timeout.TotalMilliseconds;
+ if (ms < Timeout.Infinite || ms > Int32.MaxValue)
+ throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
+
+ return Join_internal (Internal, (int) ms, Internal.system_thread_handle);
}
+#endif
#if NET_1_1
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static void MemoryBarrier ();
#endif
+
+#if !MOONLIGHT
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern void Resume_internal();
-#if NET_2_0
[Obsolete ("")]
-#endif
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
public void Resume ()
{
Resume_internal ();
}
+#endif // !NET_2_1
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static void SpinWait_internal (int iterations);
+ private extern static void SpinWait_nop ();
-#if NET_2_0
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
-#endif
public static void SpinWait (int iterations)
{
- SpinWait_internal (iterations);
+ if (iterations < 0)
+ return;
+ while (iterations-- > 0)
+ {
+ SpinWait_nop ();
+ }
+ }
+
+#if MOONLIGHT
+ private void StartSafe ()
+ {
+ current_thread = this;
+
+ try {
+ if (threadstart is ThreadStart) {
+ ((ThreadStart) threadstart) ();
+ } else {
+ ((ParameterizedThreadStart) threadstart) (start_obj);
+ }
+ } catch (ThreadAbortException) {
+ // do nothing
+ } catch (Exception ex) {
+ MoonlightUnhandledException (ex);
+ }
+ }
+
+ static MethodInfo moonlight_unhandled_exception = null;
+
+ static internal void MoonlightUnhandledException (Exception e)
+ {
+ try {
+ if (moonlight_unhandled_exception == null) {
+ var assembly = System.Reflection.Assembly.Load ("System.Windows, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e");
+ var application = assembly.GetType ("System.Windows.Application");
+ moonlight_unhandled_exception = application.GetMethod ("OnUnhandledException",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
+ }
+ moonlight_unhandled_exception.Invoke (null, new object [] { null, e });
+ }
+ catch {
+ try {
+ Console.WriteLine ("Unexpected exception while trying to report unhandled application exception: {0}", e);
+ } catch {
+ }
+ }
+ }
+#endif
+
+ private void StartUnsafe ()
+ {
+ current_thread = this;
+
+ if (threadstart is ThreadStart) {
+ ((ThreadStart) threadstart) ();
+ } else {
+ ((ParameterizedThreadStart) threadstart) (start_obj);
+ }
}
public void Start() {
// 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;
+ ec_to_set = ExecutionContext.Capture ();
+ Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
// Thread_internal creates and starts the new thread,
- if (Thread_internal(threadstart) == (IntPtr) 0)
+#if MOONLIGHT
+ if (Thread_internal((ThreadStart) StartSafe) == (IntPtr) 0)
+#else
+ if (Thread_internal((ThreadStart) StartUnsafe) == (IntPtr) 0)
+#endif
throw new SystemException ("Thread creation failed.");
}
+#if !MOONLIGHT
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private extern void Suspend_internal();
+ private extern static void Suspend_internal(InternalThread thread);
-#if NET_2_0
[Obsolete ("")]
-#endif
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
public void Suspend ()
{
- Suspend_internal ();
- }
-
- // Closes the system thread handle
- [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);
+ Suspend_internal (Internal);
}
+#endif // !NET_2_1
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern private void SetState (ThreadState set);
-
+ extern private static void SetState (InternalThread thread, ThreadState set);
+
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern private void ClrState (ThreadState clr);
-
+ extern private static void ClrState (InternalThread thread, ThreadState clr);
+
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern private ThreadState GetState ();
+ extern private static ThreadState GetState (InternalThread thread);
#if NET_1_1
#endif
-#if NET_2_0
+ private static int GetNewManagedId() {
+ return Interlocked.Increment(ref _managed_id_counter);
+ }
+
public Thread (ThreadStart start, int maxStackSize)
{
if (start == null)
throw new ArgumentException ("< 128 kb", "maxStackSize");
threadstart = start;
- stack_size = maxStackSize;
+ Internal.stack_size = maxStackSize;
}
public Thread (ParameterizedThreadStart start)
throw new ArgumentException ("< 128 kb", "maxStackSize");
threadstart = start;
- stack_size = maxStackSize;
+ Internal.stack_size = maxStackSize;
}
[MonoTODO ("limited to CompressedStack support")]
- // FIXME: We share the _ec object between appdomains
public ExecutionContext ExecutionContext {
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
get {
}
public int ManagedThreadId {
- [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
- get { return (int)thread_id; }
+ [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
+ get {
+ if (Internal.managed_id == 0) {
+ int new_managed_id = GetNewManagedId ();
+
+ Interlocked.CompareExchange (ref Internal.managed_id, new_managed_id, 0);
+ }
+
+ return Internal.managed_id;
+ }
}
- [MonoTODO("Not implemented")]
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
public static void BeginCriticalRegion ()
{
- throw new NotImplementedException ();
+ CurrentThread.Internal.critical_region_level++;
}
- [MonoTODO("Not implemented")]
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
public static void EndCriticalRegion ()
{
- throw new NotImplementedException ();
+ CurrentThread.Internal.critical_region_level--;
}
- [MonoTODO("Not implemented")]
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
public static void BeginThreadAffinity ()
{
- throw new NotImplementedException ();
+ // Managed and native threads are currently bound together.
}
- [MonoTODO("Not implemented")]
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
public static void EndThreadAffinity ()
{
- throw new NotImplementedException ();
+ // Managed and native threads are currently bound together.
}
-
+
+#if !MOONLIGHT
public ApartmentState GetApartmentState ()
{
- return (ApartmentState)apartment_state;
+ return (ApartmentState)Internal.apartment_state;
}
public void SetApartmentState (ApartmentState state)
public bool TrySetApartmentState (ApartmentState state)
{
- if ((ThreadState & ThreadState.Unstarted) == 0)
+ /* Only throw this exception when changing the
+ * state of another thread. See bug 324338
+ */
+ if ((this != CurrentThread) &&
+ (ThreadState & ThreadState.Unstarted) == 0)
throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
- if ((ApartmentState)apartment_state != ApartmentState.Unknown)
+ if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown)
return false;
- apartment_state = (byte)state;
+ Internal.apartment_state = (byte)state;
return true;
}
+#endif // !NET_2_1
[ComVisible (false)]
public override int GetHashCode ()
{
- // ??? overridden but not guaranteed to be unique ???
- return (int)thread_id;
+ return ManagedThreadId;
}
public void Start (object parameter)
start_obj = parameter;
Start ();
}
-#else
- internal ExecutionContext ExecutionContext {
- get {
- if (_ec == null)
- _ec = new ExecutionContext ();
- return _ec;
- }
- }
-#endif
+#if !MOONLIGHT
// 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
// 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
ExecutionContext.SecurityContext.CompressedStack = stack;
}
+#endif
+
#if NET_1_1
void _Thread.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
{