Imported Upstream version 6.4.0.137

Former-commit-id: 943baa9f16a098c33e129777827f3a9d20da00d6
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-07-26 19:53:28 +00:00
parent e9207cf623
commit ef583813eb
2712 changed files with 74169 additions and 40587 deletions

View File

@@ -0,0 +1,87 @@
using Microsoft.Win32.SafeHandles;
using System.Runtime.CompilerServices;
namespace System.Threading
{
partial class EventWaitHandle
{
public bool Set ()
{
SafeWaitHandle handle = ValidateHandle (out bool release);
try {
return SetEventInternal (handle.DangerousGetHandle ());
} finally {
if (release)
handle.DangerousRelease ();
}
}
public bool Reset ()
{
SafeWaitHandle handle = ValidateHandle (out bool release);
try {
return ResetEventInternal (handle.DangerousGetHandle ());
} finally {
if (release)
handle.DangerousRelease ();
}
}
unsafe void CreateEventCore (bool initialState, EventResetMode mode, string name, out bool createdNew)
{
if (name != null)
throw new PlatformNotSupportedException (SR.PlatformNotSupported_NamedSynchronizationPrimitives);
SafeWaitHandle handle = new SafeWaitHandle (CreateEventInternal (mode == EventResetMode.ManualReset, initialState, null, 0, out int errorCode), ownsHandle: true);
if (errorCode != 0)
throw new NotImplementedException ("errorCode");
SafeWaitHandle = handle;
createdNew = true;
}
static OpenExistingResult OpenExistingWorker (string name, out EventWaitHandle result)
{
throw new PlatformNotSupportedException (SR.PlatformNotSupported_NamedSynchronizationPrimitives);
}
internal static bool Set (SafeWaitHandle waitHandle)
{
bool release = false;
try {
waitHandle.DangerousAddRef (ref release);
return SetEventInternal (waitHandle.DangerousGetHandle ());
} finally {
if (release)
waitHandle.DangerousRelease ();
}
}
SafeWaitHandle ValidateHandle (out bool success)
{
// The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
// to ensure that one instance is used in all places in this method
SafeWaitHandle waitHandle = SafeWaitHandle;
if (waitHandle.IsInvalid)
{
throw new InvalidOperationException ();
}
success = false;
waitHandle.DangerousAddRef (ref success);
return waitHandle;
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
unsafe static extern IntPtr CreateEventInternal (bool manual, bool initialState, char *name, int name_length, out int errorCode);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern bool ResetEventInternal (IntPtr handle);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern bool SetEventInternal (IntPtr handle);
}
}

View File

@@ -0,0 +1,75 @@
using System.Runtime.CompilerServices;
namespace System.Threading
{
public static class Interlocked
{
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static int CompareExchange (ref int location1, int value, int comparand);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static object CompareExchange (ref object location1, object value, object comparand);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static float CompareExchange (ref float location1, float value, float comparand);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static int Decrement (ref int location);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static long Decrement (ref long location);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static int Increment (ref int location);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static long Increment (ref long location);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static int Exchange (ref int location1, int value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static object Exchange (ref object location1, object value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static float Exchange (ref float location1, float value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static long CompareExchange (ref long location1, long value, long comparand);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static IntPtr CompareExchange (ref IntPtr location1, IntPtr value, IntPtr comparand);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static double CompareExchange (ref double location1, double value, double comparand);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static T CompareExchange<T> (ref T location1, T value, T comparand) where T : class;
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static long Exchange (ref long location1, long value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static IntPtr Exchange (ref IntPtr location1, IntPtr value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static double Exchange (ref double location1, double value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static T Exchange<T> (ref T location1, T value) where T : class;
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static long Read (ref long location);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static int Add (ref int location1, int value);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static long Add (ref long location1, long value);
public static void MemoryBarrier () => Thread.MemoryBarrier ();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static void MemoryBarrierProcessWide ();
}
}

View File

@@ -0,0 +1,173 @@
using System.Runtime.CompilerServices;
namespace System.Threading
{
public static partial class Monitor
{
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public static extern void Enter (object obj);
public static void Enter (object obj, ref bool lockTaken)
{
if (lockTaken)
throw new ArgumentException (SR.Argument_MustBeFalse, nameof (lockTaken));
ReliableEnter (obj, ref lockTaken);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public static extern void Exit (object obj);
public static bool TryEnter (object obj)
{
bool lockTaken = false;
TryEnter (obj, 0, ref lockTaken);
return lockTaken;
}
public static void TryEnter (object obj, ref bool lockTaken)
{
if (lockTaken)
throw new ArgumentException (SR.Argument_MustBeFalse, nameof (lockTaken));
ReliableEnterTimeout (obj, 0, ref lockTaken);
}
public static bool TryEnter (object obj, int millisecondsTimeout)
{
bool lockTaken = false;
TryEnter (obj, millisecondsTimeout, ref lockTaken);
return lockTaken;
}
static int MillisecondsTimeoutFromTimeSpan (TimeSpan timeout)
{
long tm = (long) timeout.TotalMilliseconds;
if (tm < -1 || tm > (long) int.MaxValue)
throw new ArgumentOutOfRangeException (nameof (timeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
return (int) tm;
}
public static bool TryEnter (object obj, TimeSpan timeout)
{
return TryEnter (obj, MillisecondsTimeoutFromTimeSpan (timeout));
}
public static void TryEnter (object obj, int millisecondsTimeout, ref bool lockTaken)
{
if (lockTaken)
throw new ArgumentException (SR.Argument_MustBeFalse, nameof (lockTaken));
ReliableEnterTimeout (obj, millisecondsTimeout, ref lockTaken);
}
public static void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken)
{
if (lockTaken)
throw new ArgumentException (SR.Argument_MustBeFalse, nameof (lockTaken));
ReliableEnterTimeout (obj, MillisecondsTimeoutFromTimeSpan (timeout), ref lockTaken);
}
public static bool IsEntered (object obj)
{
if (obj == null)
throw new ArgumentNullException (nameof (obj));
return IsEnteredNative (obj);
}
public static bool Wait (object obj, int millisecondsTimeout, bool exitContext)
{
if (obj == null)
throw new ArgumentNullException (nameof (obj));
return ObjWait (exitContext, millisecondsTimeout, obj);
}
public static bool Wait (object obj, TimeSpan timeout, bool exitContext) => Wait (obj, MillisecondsTimeoutFromTimeSpan (timeout), exitContext);
public static bool Wait (object obj, int millisecondsTimeout) => Wait (obj, millisecondsTimeout, false);
public static bool Wait(object obj, TimeSpan timeout) => Wait (obj, MillisecondsTimeoutFromTimeSpan (timeout), false);
public static bool Wait(object obj) => Wait (obj, Timeout.Infinite, false);
public static void Pulse (object obj)
{
if (obj == null)
throw new ArgumentNullException (nameof (obj));
ObjPulse (obj);
}
public static void PulseAll (object obj)
{
if (obj == null)
throw new ArgumentNullException (nameof (obj));
ObjPulseAll (obj);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static bool Monitor_test_synchronised (object obj);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void Monitor_pulse (object obj);
static void ObjPulse (object obj)
{
if (!Monitor_test_synchronised (obj))
throw new SynchronizationLockException ("Object is not synchronized");
Monitor_pulse (obj);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void Monitor_pulse_all (object obj);
static void ObjPulseAll (object obj)
{
if (!Monitor_test_synchronised (obj))
throw new SynchronizationLockException ("Object is not synchronized");
Monitor_pulse_all (obj);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static bool Monitor_wait (object obj, int ms);
static bool ObjWait (bool exitContext, int millisecondsTimeout, object obj)
{
if (millisecondsTimeout < 0 && millisecondsTimeout != (int) Timeout.Infinite)
throw new ArgumentOutOfRangeException ("millisecondsTimeout");
if (!Monitor_test_synchronised (obj))
throw new SynchronizationLockException ("Object is not synchronized");
return Monitor_wait (obj, millisecondsTimeout);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void try_enter_with_atomic_var (object obj, int millisecondsTimeout, ref bool lockTaken);
static void ReliableEnterTimeout (object obj, int timeout, ref bool lockTaken)
{
if (obj == null)
throw new ArgumentNullException (nameof (obj));
if (timeout < 0 && timeout != (int) Timeout.Infinite)
throw new ArgumentOutOfRangeException (nameof (timeout));
try_enter_with_atomic_var (obj, timeout, ref lockTaken);
}
static void ReliableEnter (object obj, ref bool lockTaken)
{
ReliableEnterTimeout (obj, (int) Timeout.Infinite, ref lockTaken);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static bool Monitor_test_owner (object obj);
static bool IsEnteredNative (object obj)
{
return Monitor_test_owner (obj);
}
public static long LockContentionCount => throw new PlatformNotSupportedException ();
}
}

View File

@@ -0,0 +1,68 @@
using System.Runtime.CompilerServices;
using System.IO;
namespace System.Threading
{
partial class Mutex
{
Mutex (IntPtr handle) => Handle = handle;
public void ReleaseMutex ()
{
if (!ReleaseMutex_internal (Handle))
throw new ApplicationException (SR.Arg_SynchronizationLockException);
}
void CreateMutexCore (bool initiallyOwned, string name, out bool createdNew) =>
Handle = CreateMutex_internal (initiallyOwned, name, out createdNew);
unsafe static IntPtr CreateMutex_internal (bool initiallyOwned, string name, out bool created)
{
fixed (char *fixed_name = name)
return CreateMutex_icall (initiallyOwned, fixed_name,
name?.Length ?? 0, out created);
}
static OpenExistingResult OpenExistingWorker (string name, out Mutex result)
{
if (name == null)
throw new ArgumentNullException (nameof (name));
result = null;
if ((name.Length == 0) ||
(name.Length > 260)) {
return OpenExistingResult.NameInvalid;
}
MonoIOError error;
IntPtr handle = OpenMutex_internal (name, out error);
if (handle == IntPtr.Zero) {
if (error == MonoIOError.ERROR_FILE_NOT_FOUND) {
return OpenExistingResult.NameNotFound;
} else if (error == MonoIOError.ERROR_ACCESS_DENIED) {
throw new UnauthorizedAccessException ();
} else {
return OpenExistingResult.PathNotFound;
}
}
result = new Mutex (handle);
return OpenExistingResult.Success;
}
unsafe static IntPtr OpenMutex_internal (string name, out MonoIOError error)
{
fixed (char *fixed_name = name)
return OpenMutex_icall (fixed_name, name?.Length ?? 0, 0x000001 /* MutexRights.Modify */, out error);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private unsafe static extern IntPtr CreateMutex_icall (bool initiallyOwned, char *name, int name_length, out bool created);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private unsafe static extern IntPtr OpenMutex_icall (char *name, int name_length, int rights, out MonoIOError error);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool ReleaseMutex_internal (IntPtr handle);
}
}

View File

@@ -0,0 +1,30 @@
namespace System.Threading
{
public class Overlapped
{
public Overlapped() { }
[System.ObsoleteAttribute("This constructor is not 64-bit compatible. Use the constructor that takes an IntPtr for the event handle. https://go.microsoft.com/fwlink/?linkid=14202")]
public Overlapped(int offsetLo, int offsetHi, int hEvent, System.IAsyncResult ar) { }
public Overlapped(int offsetLo, int offsetHi, System.IntPtr hEvent, System.IAsyncResult ar) { }
public System.IAsyncResult AsyncResult { get { throw null; } set { } }
[System.ObsoleteAttribute("This property is not 64-bit compatible. Use EventHandleIntPtr instead. https://go.microsoft.com/fwlink/?linkid=14202")]
public int EventHandle { get { throw null; } set { } }
public System.IntPtr EventHandleIntPtr { get { throw null; } set { } }
public int OffsetHigh { get { throw null; } set { } }
public int OffsetLow { get { throw null; } set { } }
[System.CLSCompliantAttribute(false)]
public static unsafe void Free(System.Threading.NativeOverlapped* nativeOverlappedPtr) { }
[System.CLSCompliantAttribute(false)]
[System.ObsoleteAttribute("This method is not safe. Use Pack (iocb, userData) instead. https://go.microsoft.com/fwlink/?linkid=14202")]
public unsafe System.Threading.NativeOverlapped* Pack(System.Threading.IOCompletionCallback iocb) { throw null; }
[System.CLSCompliantAttribute(false)]
public unsafe System.Threading.NativeOverlapped* Pack(System.Threading.IOCompletionCallback iocb, object userData) { throw null; }
[System.CLSCompliantAttribute(false)]
public static unsafe System.Threading.Overlapped Unpack(System.Threading.NativeOverlapped* nativeOverlappedPtr) { throw null; }
[System.CLSCompliantAttribute(false)]
[System.ObsoleteAttribute("This method is not safe. Use UnsafePack (iocb, userData) instead. https://go.microsoft.com/fwlink/?linkid=14202")]
public unsafe System.Threading.NativeOverlapped* UnsafePack(System.Threading.IOCompletionCallback iocb) { throw null; }
[System.CLSCompliantAttribute(false)]
public unsafe System.Threading.NativeOverlapped* UnsafePack(System.Threading.IOCompletionCallback iocb, object userData) { throw null; }
}
}

View File

@@ -0,0 +1,9 @@
namespace System.Threading
{
public sealed class PreAllocatedOverlapped : System.IDisposable
{
[System.CLSCompliantAttribute(false)]
public PreAllocatedOverlapped(System.Threading.IOCompletionCallback callback, object state, object pinData) { }
public void Dispose() { }
}
}

View File

@@ -0,0 +1,91 @@
using System.Runtime.InteropServices;
namespace System.Threading
{
public sealed class RegisteredWaitHandle : MarshalByRefObject
{
WaitHandle _waitObject;
WaitOrTimerCallback _callback;
object _state;
WaitHandle _finalEvent;
ManualResetEvent _cancelEvent;
TimeSpan _timeout;
int _callsInProcess;
bool _executeOnlyOnce;
bool _unregistered;
internal RegisteredWaitHandle (WaitHandle waitObject, WaitOrTimerCallback callback, object state, TimeSpan timeout, bool executeOnlyOnce)
{
_waitObject = waitObject;
_callback = callback;
_state = state;
_timeout = timeout;
_executeOnlyOnce = executeOnlyOnce;
_cancelEvent = new ManualResetEvent (false);
}
internal void Wait (object? state)
{
bool release = false;
try {
_waitObject.SafeWaitHandle.DangerousAddRef (ref release);
try {
WaitHandle[] waits = new WaitHandle[] {_waitObject, _cancelEvent};
do {
int signal = WaitHandle.WaitAny (waits, _timeout, false);
if (!_unregistered) {
lock (this) {
_callsInProcess++;
}
ThreadPool.QueueUserWorkItem (new WaitCallback (DoCallBack), (signal == WaitHandle.WaitTimeout));
}
} while (!_unregistered && !_executeOnlyOnce);
} catch {
}
lock (this) {
_unregistered = true;
if (_callsInProcess == 0 && _finalEvent != null)
throw new NotImplementedException ();
}
} catch (ObjectDisposedException) {
// Can happen if we called Unregister before we had time to execute Wait
if (release)
throw;
} finally {
if (release)
_waitObject.SafeWaitHandle.DangerousRelease ();
}
}
void DoCallBack (object? timedOut)
{
try {
if (_callback != null)
_callback (_state, (bool)timedOut!);
} finally {
lock (this) {
_callsInProcess--;
if (_unregistered && _callsInProcess == 0 && _finalEvent != null) {
EventWaitHandle.Set (_finalEvent.SafeWaitHandle);
_finalEvent = null;
}
}
}
}
public bool Unregister(WaitHandle waitObject)
{
lock (this) {
if (_unregistered)
return false;
_finalEvent = waitObject;
_unregistered = true;
_cancelEvent.Set();
return true;
}
}
}
}

View File

@@ -0,0 +1,98 @@
using System.Runtime.CompilerServices;
using Microsoft.Win32.SafeHandles;
using System.IO;
namespace System.Threading
{
partial class Semaphore
{
const int MAX_PATH = 260;
Semaphore (SafeWaitHandle handle) => this.SafeWaitHandle = handle;
int ReleaseCore (int releaseCount)
{
if (!ReleaseSemaphore_internal (SafeWaitHandle.DangerousGetHandle (), releaseCount, out int previousCount))
throw new SemaphoreFullException ();
return previousCount;
}
static OpenExistingResult OpenExistingWorker (string name, out Semaphore result)
{
if (name == null)
throw new ArgumentNullException (nameof (name));
if (name.Length == 0)
throw new ArgumentException (SR.Argument_StringZeroLength, nameof (name));
if (name.Length > MAX_PATH)
throw new ArgumentException (SR.Argument_WaitHandleNameTooLong);
var myHandle = new SafeWaitHandle (OpenSemaphore_internal (name,
/*SemaphoreRights.Modify | SemaphoreRights.Synchronize*/ 0x000002 | 0x100000,
out MonoIOError errorCode), true);
if (myHandle.IsInvalid) {
result = null;
switch (errorCode) {
case MonoIOError.ERROR_FILE_NOT_FOUND:
case MonoIOError.ERROR_INVALID_NAME:
return OpenExistingResult.NameNotFound;
case MonoIOError.ERROR_PATH_NOT_FOUND:
return OpenExistingResult.PathNotFound;
case MonoIOError.ERROR_INVALID_HANDLE when !string.IsNullOrEmpty (name):
return OpenExistingResult.NameInvalid;
default:
//this is for passed through NativeMethods Errors
throw new IOException ($"Unknown Error '{errorCode}'");
}
}
result = new Semaphore (myHandle);
return OpenExistingResult.Success;
}
void CreateSemaphoreCore (int initialCount, int maximumCount, string name, out bool createdNew)
{
if (name?.Length > MAX_PATH)
throw new ArgumentException (SR.Argument_WaitHandleNameTooLong);
var myHandle = new SafeWaitHandle (CreateSemaphore_internal (initialCount, maximumCount, name, out MonoIOError errorCode), true);
if (myHandle.IsInvalid) {
if (errorCode == MonoIOError.ERROR_INVALID_HANDLE && !string.IsNullOrEmpty (name))
throw new WaitHandleCannotBeOpenedException (SR.Format (SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
throw new IOException ($"Unknown Error '{errorCode}'");
}
this.SafeWaitHandle = myHandle;
createdNew = errorCode != MonoIOError.ERROR_ALREADY_EXISTS;
}
unsafe static IntPtr CreateSemaphore_internal (int initialCount, int maximumCount, string name, out MonoIOError errorCode)
{
// FIXME Check for embedded nuls in name.
fixed (char *fixed_name = name)
return CreateSemaphore_icall (initialCount, maximumCount,
fixed_name, name?.Length ?? 0, out errorCode);
}
unsafe static IntPtr OpenSemaphore_internal (string name, int rights, out MonoIOError errorCode)
{
// FIXME Check for embedded nuls in name.
fixed (char *fixed_name = name)
return OpenSemaphore_icall (fixed_name, name?.Length ?? 0, rights, out errorCode);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
unsafe static extern IntPtr CreateSemaphore_icall (int initialCount, int maximumCount, char* name, int nameLength, out MonoIOError errorCode);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
unsafe static extern IntPtr OpenSemaphore_icall (char* name, int nameLength, int rights, out MonoIOError errorCode);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern bool ReleaseSemaphore_internal (IntPtr handle, int releaseCount, out int previousCount);
}
}

View File

@@ -0,0 +1,13 @@
namespace System.Threading
{
// declaring a local var of this enum type and passing it by ref into a function that needs to do a
// stack crawl will both prevent inlining of the calle and pass an ESP point to stack crawl to
// Declaring these in EH clauses is illegal; they must declared in the main method body
internal enum StackCrawlMark
{
LookForMe = 0,
LookForMyCaller = 1,
LookForMyCallersCaller = 2,
LookForThread = 3
}
}

View File

@@ -0,0 +1,316 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Threading
{
//
// Under netcore, there is only one thread object per thread
//
[StructLayout (LayoutKind.Sequential)]
partial class Thread
{
#pragma warning disable 169, 414, 649
#region Sync with metadata/object-internals.h and InternalThread in mcs/class/corlib/System.Threading/Thread.cs
int lock_thread_id;
// stores a thread handle
IntPtr handle;
IntPtr native_handle; // used only on Win32
IntPtr unused3;
/* accessed only from unmanaged code */
private IntPtr name;
private int name_len;
private ThreadState state;
private object abort_exc;
private int abort_state_handle;
/* thread_id is only accessed from unmanaged code */
internal Int64 thread_id;
private IntPtr debugger_thread; // FIXME switch to bool as soon as CI testing with corlib version bump works
private UIntPtr static_data; /* GC-tracked */
private IntPtr runtime_thread_info;
/* current System.Runtime.Remoting.Contexts.Context instance
keep as an object to avoid triggering its class constructor when not needed */
private object current_appcontext;
private object root_domain_thread;
internal byte[] _serialized_principal;
internal int _serialized_principal_version;
private IntPtr appdomain_refs;
private int interruption_requested;
private IntPtr longlived;
internal bool threadpool_thread;
private bool thread_interrupt_requested;
/* These are used from managed code */
internal int stack_size;
internal byte apartment_state;
internal volatile int critical_region_level;
internal int managed_id;
private int small_id;
private IntPtr manage_callback;
private IntPtr unused4;
private IntPtr flags;
private IntPtr thread_pinning_ref;
private IntPtr abort_protected_block_count;
private int priority;
private IntPtr owned_mutex;
private IntPtr suspended_event;
private int self_suspended;
private IntPtr thread_state;
private Thread self;
private object pending_exception;
private object start_obj;
/* This is used only to check that we are in sync between the representation
* of MonoInternalThread in native and InternalThread in managed
*
* DO NOT RENAME! DO NOT ADD FIELDS AFTER! */
private IntPtr last;
#endregion
#pragma warning restore 169, 414, 649
string _name;
Delegate m_start;
object m_start_arg;
CultureInfo culture, ui_culture;
internal ExecutionContext _executionContext;
internal SynchronizationContext _synchronizationContext;
Thread ()
{
InitInternal (this);
}
~Thread ()
{
FreeInternal ();
}
internal static ulong CurrentOSThreadId {
get {
throw new NotImplementedException ();
}
}
public bool IsAlive {
get {
var state = GetState (this);
return (state & (ThreadState.Unstarted | ThreadState.Stopped | ThreadState.Aborted)) == 0;
}
}
public bool IsBackground {
get {
var state = ValidateThreadState ();
return (state & ThreadState.Background) != 0;
}
set {
ValidateThreadState ();
if (value) {
SetState (this, ThreadState.Background);
} else {
ClrState (this, ThreadState.Background);
}
}
}
public bool IsThreadPoolThread {
get {
ValidateThreadState ();
return threadpool_thread;
}
}
public int ManagedThreadId => managed_id;
internal static int OptimalMaxSpinWaitsPerSpinIteration {
get {
// Default from coreclr (src/utilcode/yieldprocessornormalized.cpp)
return 7;
}
}
public ThreadPriority Priority {
get {
ValidateThreadState ();
return (ThreadPriority) priority;
}
set {
// TODO: arguments check
SetPriority (this, (int) value);
}
}
internal SynchronizationContext SynchronizationContext { get; set; }
public ThreadState ThreadState => GetState (this);
void Create (ThreadStart start) => SetStartHelper ((Delegate) start, 0); // 0 will setup Thread with default stackSize
void Create (ThreadStart start, int maxStackSize) => SetStartHelper ((Delegate) start, maxStackSize);
void Create (ParameterizedThreadStart start) => SetStartHelper ((Delegate) start, 0);
void Create (ParameterizedThreadStart start, int maxStackSize) => SetStartHelper ((Delegate) start, maxStackSize);
public ApartmentState GetApartmentState () => ApartmentState.Unknown;
public void DisableComObjectEagerCleanup ()
{
// no-op
}
public static int GetCurrentProcessorId ()
{
// TODO: Implement correctly
return Environment.CurrentManagedThreadId;
}
public void Interrupt ()
{
InterruptInternal (this);
}
public bool Join (int millisecondsTimeout)
{
if (millisecondsTimeout < Timeout.Infinite)
throw new ArgumentOutOfRangeException (nameof (millisecondsTimeout), millisecondsTimeout, SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
return JoinInternal (this, millisecondsTimeout);
}
public void ResetThreadPoolThread ()
{
}
void SetCultureOnUnstartedThreadNoCheck (CultureInfo value, bool uiCulture)
{
if (uiCulture)
ui_culture = value;
else
culture = value;
}
void SetStartHelper (Delegate start, int maxStackSize)
{
m_start = start;
stack_size = maxStackSize;
}
public static void SpinWait (int iterations)
{
if (iterations < 0)
return;
while (iterations-- > 0)
SpinWait_nop ();
}
public static void Sleep (int millisecondsTimeout)
{
if (millisecondsTimeout < Timeout.Infinite)
throw new ArgumentOutOfRangeException (nameof (millisecondsTimeout), millisecondsTimeout, SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
SleepInternal (millisecondsTimeout);
}
public void Start ()
{
StartInternal (this);
}
public void Start (object parameter)
{
if (m_start is ThreadStart)
throw new InvalidOperationException (SR.InvalidOperation_ThreadWrongThreadStart);
m_start_arg = parameter;
StartInternal (this);
}
// Called from the runtime
internal void StartCallback ()
{
if (culture != null)
CurrentCulture = culture;
if (ui_culture != null)
CurrentUICulture = ui_culture;
if (m_start is ThreadStart del) {
m_start = null;
del ();
} else {
var pdel = (ParameterizedThreadStart) m_start;
var arg = m_start_arg;
m_start = null;
m_start_arg = null;
pdel (arg);
}
}
partial void ThreadNameChanged (string value)
{
// TODO: Should only raise the events
SetName (this, value);
}
public static bool Yield ()
{
return YieldInternal ();
}
public bool TrySetApartmentStateUnchecked (ApartmentState state) => state == ApartmentState.Unknown;
ThreadState ValidateThreadState ()
{
var state = GetState (this);
if ((state & ThreadState.Stopped) != 0)
throw new ThreadStateException ("Thread is dead; state can not be accessed.");
return state;
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void InitInternal (Thread thread);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static Thread InitializeCurrentThread ();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern void FreeInternal ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static ThreadState GetState (Thread thread);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void SetState (Thread thread, ThreadState set);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void ClrState (Thread thread, ThreadState clr);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static string GetName (Thread thread);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static void SetName (Thread thread, String name);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static bool YieldInternal ();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static void SleepInternal (int millisecondsTimeout);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void SpinWait_nop ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static Thread CreateInternal ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern static void StartInternal (Thread runtime_thread);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static bool JoinInternal (Thread thread, int millisecondsTimeout);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static void InterruptInternal (Thread thread);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static void SetPriority (Thread thread, int priority);
}
}

View File

@@ -0,0 +1,131 @@
using System.Runtime.CompilerServices;
namespace System.Threading
{
partial class ThreadPool
{
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern void InitializeVMTp (ref bool enableWorkerTracking);
static void EnsureInitialized ()
{
if (!ThreadPoolGlobals.threadPoolInitialized) {
ThreadPool.InitializeVMTp (ref ThreadPoolGlobals.enableWorkerTracking);
ThreadPoolGlobals.threadPoolInitialized = true;
}
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern bool RequestWorkerThread ();
internal static bool KeepDispatching (int startTickCount) => true;
internal static void NotifyWorkItemProgress ()
{
EnsureInitialized ();
NotifyWorkItemProgressNative ();
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern void NotifyWorkItemProgressNative ();
static RegisteredWaitHandle RegisterWaitForSingleObject (WaitHandle waitObject, WaitOrTimerCallback callBack, object state,
uint millisecondsTimeOutInterval, bool executeOnlyOnce, bool compressStack)
{
if (waitObject == null)
throw new ArgumentNullException ("waitObject");
if (callBack == null)
throw new ArgumentNullException ("callBack");
if (millisecondsTimeOutInterval != Timeout.UnsignedInfinite && millisecondsTimeOutInterval > Int32.MaxValue)
throw new NotSupportedException ("Timeout is too big. Maximum is Int32.MaxValue");
RegisteredWaitHandle waiter = new RegisteredWaitHandle (waitObject, callBack, state, new TimeSpan (0, 0, 0, 0, (int) millisecondsTimeOutInterval), executeOnlyOnce);
if (compressStack)
QueueUserWorkItem (new WaitCallback (waiter.Wait), null);
else
UnsafeQueueUserWorkItem (new WaitCallback (waiter.Wait), null);
return waiter;
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern void ReportThreadStatus (bool isWorking);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern bool NotifyWorkItemComplete ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern bool SetMinThreadsNative (int workerThreads, int completionPortThreads);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern bool SetMaxThreadsNative (int workerThreads, int completionPortThreads);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern void GetMinThreadsNative (out int workerThreads, out int completionPortThreads);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern void GetMaxThreadsNative (out int workerThreads, out int completionPortThreads);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
static extern void GetAvailableThreadsNative (out int workerThreads, out int completionPortThreads);
public static bool SetMaxThreads (int workerThreads, int completionPortThreads)
{
return SetMaxThreadsNative (workerThreads, completionPortThreads);
}
public static void GetMaxThreads (out int workerThreads, out int completionPortThreads)
{
GetMaxThreadsNative (out workerThreads, out completionPortThreads);
}
public static bool SetMinThreads (int workerThreads, int completionPortThreads)
{
return SetMinThreadsNative (workerThreads, completionPortThreads);
}
public static void GetMinThreads (out int workerThreads, out int completionPortThreads)
{
GetMinThreadsNative (out workerThreads, out completionPortThreads);
}
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads)
{
GetAvailableThreadsNative (out workerThreads, out completionPortThreads);
}
public static bool BindHandle (IntPtr osHandle) => throw new NotImplementedException ();
public static bool BindHandle (System.Runtime.InteropServices.SafeHandle osHandle) => throw new NotImplementedException ();
[CLSCompliant (false)]
public static unsafe bool UnsafeQueueNativeOverlapped (NativeOverlapped* overlapped) => throw new NotImplementedException ();
static long PendingUnmanagedWorkItemCount => 0;
public static long CompletedWorkItemCount => throw new PlatformNotSupportedException ();
public static int ThreadCount => throw new NotImplementedException ();
}
internal static class _ThreadPoolWaitCallback
{
// This feature is used by Xamarin.iOS to use an NSAutoreleasePool
// for every task done by the threadpool.
static Func<Func<bool>, bool> dispatcher;
internal static void SetDispatcher (Func<Func<bool>, bool> value)
{
dispatcher = value;
}
static internal bool PerformWaitCallback ()
{
// store locally first to ensure another thread doesn't clear the field between checking for null and using it.
var dispatcher = _ThreadPoolWaitCallback.dispatcher;
if (dispatcher != null)
return dispatcher (ThreadPoolWorkQueue.Dispatch);
return ThreadPoolWorkQueue.Dispatch ();
}
}
}

View File

@@ -0,0 +1,18 @@
namespace System.Threading
{
public sealed partial class ThreadPoolBoundHandle : System.IDisposable
{
internal ThreadPoolBoundHandle() { }
public System.Runtime.InteropServices.SafeHandle Handle { get { throw null; } }
[System.CLSCompliantAttribute(false)]
public unsafe System.Threading.NativeOverlapped* AllocateNativeOverlapped(System.Threading.IOCompletionCallback callback, object state, object pinData) { throw null; }
[System.CLSCompliantAttribute(false)]
public unsafe System.Threading.NativeOverlapped* AllocateNativeOverlapped(System.Threading.PreAllocatedOverlapped preAllocated) { throw null; }
public static System.Threading.ThreadPoolBoundHandle BindHandle(System.Runtime.InteropServices.SafeHandle handle) { throw null; }
public void Dispose() { }
[System.CLSCompliantAttribute(false)]
public unsafe void FreeNativeOverlapped(System.Threading.NativeOverlapped* overlapped) { }
[System.CLSCompliantAttribute(false)]
public static unsafe object GetNativeOverlappedState(System.Threading.NativeOverlapped* overlapped) { throw null; }
}
}

View File

@@ -0,0 +1,43 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Threading
{
partial class WaitHandle
{
[MethodImplAttribute(MethodImplOptions.InternalCall)]
unsafe static extern int Wait_internal(IntPtr* handles, int numHandles, bool waitAll, int ms);
static int WaitOneCore (IntPtr waitHandle, int millisecondsTimeout)
{
unsafe {
return Wait_internal (&waitHandle, 1, false, millisecondsTimeout);
}
}
[MethodImpl (MethodImplOptions.InternalCall)]
static extern int SignalAndWait_Internal (IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout);
const int ERROR_TOO_MANY_POSTS = 0x12A;
const int ERROR_NOT_OWNED_BY_CALLER = 0x12B;
static int SignalAndWaitCore (IntPtr waitHandleToSignal, IntPtr waitHandleToWaitOn, int millisecondsTimeout)
{
int ret = SignalAndWait_Internal (waitHandleToSignal, waitHandleToWaitOn, millisecondsTimeout);
if (ret == ERROR_TOO_MANY_POSTS)
throw new InvalidOperationException (SR.Threading_WaitHandleTooManyPosts);
if (ret == ERROR_NOT_OWNED_BY_CALLER)
throw new ApplicationException("Attempt to release mutex not owned by caller");
return ret;
}
internal static int WaitMultipleIgnoringSyncContext (Span<IntPtr> waitHandles, bool waitAll, int millisecondsTimeout)
{
unsafe {
fixed (IntPtr* handles = &MemoryMarshal.GetReference (waitHandles)) {
return Wait_internal (handles, waitHandles.Length, waitAll, millisecondsTimeout);
}
}
}
}
}