Imported Upstream version 6.0.0.172

Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-04-12 14:10:50 +00:00
parent 8016999e4d
commit 64ac736ec5
32155 changed files with 3981439 additions and 75368 deletions

View File

@@ -38,7 +38,7 @@ using System.Runtime.ConstrainedExecution;
namespace System.Threading
{
public static class Interlocked
public static partial class Interlocked
{
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]

View File

@@ -31,7 +31,9 @@
//
using System.Runtime.CompilerServices;
#if !DISABLE_REMOTING
using System.Runtime.Remoting.Contexts;
#endif
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;

View File

@@ -41,17 +41,30 @@ namespace System.Threading
[ComVisible (true)]
public sealed class Mutex : WaitHandle
{
[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,
MutexRights rights, out MonoIOError error);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool ReleaseMutex_internal(IntPtr handle);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern IntPtr CreateMutex_internal(
bool initiallyOwned,
string name,
out bool created);
private 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);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private static extern IntPtr OpenMutex_internal (string name, MutexRights rights, out MonoIOError error);
private unsafe static IntPtr OpenMutex_internal (string name, MutexRights rights, out MonoIOError error)
{
fixed (char *fixed_name = name)
return OpenMutex_icall (fixed_name, name?.Length ?? 0, rights, out error);
}
private Mutex (IntPtr handle)
{

View File

@@ -35,17 +35,24 @@ using System;
using System.Runtime.CompilerServices;
using Microsoft.Win32.SafeHandles;
#if !MOBILE
#if !MOBILE && !NETCORE
using System.Security.AccessControl;
using System.IO;
#endif
namespace System.Threading
namespace System.Threading
{
internal static class NativeEventCalls
{
public unsafe static IntPtr CreateEvent_internal (bool manual, bool initial, string name, out int errorCode)
{
// FIXME check for embedded nuls in name
fixed (char *fixed_name = name)
return CreateEvent_icall (manual, initial, fixed_name, name?.Length ?? 0, out errorCode);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern IntPtr CreateEvent_internal (bool manual, bool initial, string name, out int errorCode);
private unsafe static extern IntPtr CreateEvent_icall (bool manual, bool initial, char *name, int name_length, out int errorCode);
public static bool SetEvent (SafeWaitHandle handle)
{
@@ -80,9 +87,16 @@ namespace System.Threading
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern void CloseEvent_internal (IntPtr handle);
#if !MOBILE
#if !MOBILE && !NETCORE
public unsafe static IntPtr OpenEvent_internal (string name, EventWaitHandleRights rights, out int errorCode)
{
// FIXME check for embedded nuls in name
fixed (char *fixed_name = name)
return OpenEvent_icall (fixed_name, name?.Length ?? 0, rights, out errorCode);
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
public static extern IntPtr OpenEvent_internal (string name, EventWaitHandleRights rights, out int errorCode);
private unsafe static extern IntPtr OpenEvent_icall (char *name, int name_length, EventWaitHandleRights rights, out int errorCode);
#endif
}
}

View File

@@ -27,11 +27,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
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;
@@ -42,6 +38,12 @@ using System.Security;
using System.Diagnostics;
using System.Runtime.ConstrainedExecution;
#if !NETCORE
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Remoting.Contexts;
using System.Security.Principal;
#endif
namespace System.Threading {
[StructLayout (LayoutKind.Sequential)]
sealed class InternalThread : CriticalFinalizerObject {
@@ -115,7 +117,10 @@ namespace System.Threading {
}
[StructLayout (LayoutKind.Sequential)]
public sealed partial class Thread {
#if !NETCORE
public
#endif
sealed partial class Thread {
#pragma warning disable 414
#region Sync with metadata/object-internals.h
private InternalThread internal_thread;
@@ -124,9 +129,6 @@ namespace System.Threading {
#endregion
#pragma warning restore 414
IPrincipal principal;
int principal_version;
// the name of current_thread is
// important because they are used by the runtime.
@@ -151,13 +153,6 @@ namespace System.Threading {
}
}
public static Context CurrentContext {
[SecurityPermission (SecurityAction.LinkDemand, Infrastructure=true)]
get {
return(AppDomain.InternalGetContext ());
}
}
/*
* These two methods return an array in the target
* domain with the same content as the argument. If
@@ -170,6 +165,16 @@ namespace System.Threading {
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static byte[] ByteArrayToCurrentDomain (byte[] arr);
#if !NETCORE
IPrincipal principal;
int principal_version;
public static Context CurrentContext {
get {
return(AppDomain.InternalGetContext ());
}
}
static void DeserializePrincipal (Thread th)
{
MemoryStream ms = new MemoryStream (ByteArrayToCurrentDomain (th.Internal._serialized_principal));
@@ -266,7 +271,6 @@ namespace System.Threading {
th.principal_version = th.Internal._serialized_principal_version;
return th.principal;
}
[SecurityPermission (SecurityAction.Demand, ControlPrincipal = true)]
set {
Thread th = CurrentThread;
@@ -288,6 +292,11 @@ namespace System.Threading {
}
}
public static AppDomain GetDomain() {
return AppDomain.CurrentDomain;
}
#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static Thread GetCurrentThread ();
@@ -308,10 +317,6 @@ namespace System.Threading {
}
}
public static AppDomain GetDomain() {
return AppDomain.CurrentDomain;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static int GetDomainID();
@@ -418,13 +423,11 @@ namespace System.Threading {
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void Abort_internal (InternalThread thread, object stateInfo);
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
public void Abort ()
{
Abort_internal (Internal, null);
}
[SecurityPermission (SecurityAction.Demand, ControlThread=true)]
public void Abort (object stateInfo)
{
Abort_internal (Internal, stateInfo);
@@ -483,7 +486,7 @@ namespace System.Threading {
}
}
void StartInternal (IPrincipal principal, ref StackCrawlMark stackMark)
void StartInternal (object principal, ref StackCrawlMark stackMark)
{
#if FEATURE_ROLE_BASED_SECURITY
Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
@@ -724,5 +727,7 @@ namespace System.Threading {
throw new ThreadStateException ("Thread is dead; state can not be accessed.");
return state;
}
public static int GetCurrentProcessorId() => global::Internal.Runtime.Augments.RuntimeThread.GetCurrentProcessorId();
}
}

View File

@@ -74,6 +74,7 @@ namespace System.Threading
long period_ms;
long next_run; // in ticks. Only 'Scheduler' can change it except for new timers without due time.
bool disposed;
bool is_dead, is_added;
#endregion
public Timer (TimerCallback callback, object state, int dueTime, int period)
{
@@ -111,6 +112,8 @@ namespace System.Threading
this.callback = callback;
this.state = state;
this.is_dead = false;
this.is_added = false;
Change (dueTime, period, true);
}
@@ -206,32 +209,38 @@ namespace System.Threading
[MethodImplAttribute(MethodImplOptions.InternalCall)]
static extern long GetTimeMonotonic ();
sealed class TimerComparer : IComparer {
public int Compare (object x, object y)
struct TimerComparer : IComparer, IComparer<Timer> {
int IComparer.Compare (object x, object y)
{
if (x == y)
return 0;
Timer tx = (x as Timer);
if (tx == null)
return -1;
Timer ty = (y as Timer);
if (ty == null)
return 1;
return Compare(tx, ty);
}
public int Compare (Timer tx, Timer ty)
{
long result = tx.next_run - ty.next_run;
if (result == 0)
return x == y ? 0 : -1;
return result > 0 ? 1 : -1;
return (int)Math.Sign(result);
}
}
sealed class Scheduler {
static readonly Scheduler instance = new Scheduler ();
SortedList list;
volatile bool needReSort = true;
List<Timer> list;
long current_next_run = Int64.MaxValue;
#if WASM
List<Timer> cached_new_time;
bool scheduled_zero;
void InitScheduler () {
cached_new_time = new List<Timer> (512);
}
void WakeupScheduler () {
@@ -243,7 +252,7 @@ namespace System.Threading
void RunScheduler() {
scheduled_zero = false;
int ms_wait = RunSchedulerLoop (cached_new_time);
int ms_wait = RunSchedulerLoop ();
if (ms_wait >= 0) {
WasmRuntime.ScheduleTimeout (ms_wait, this.RunScheduler);
if (ms_wait == 0)
@@ -267,12 +276,11 @@ namespace System.Threading
void SchedulerThread ()
{
Thread.CurrentThread.Name = "Timer-Scheduler";
var new_time = new List<Timer> (512);
while (true) {
int ms_wait = -1;
lock (this) {
changed.Reset ();
ms_wait = RunSchedulerLoop (new_time);
ms_wait = RunSchedulerLoop ();
}
// Wait until due time or a timer is changed and moves from/to the first place in the list.
changed.WaitOne (ms_wait);
@@ -286,16 +294,12 @@ namespace System.Threading
private Scheduler ()
{
list = new SortedList (new TimerComparer (), 1024);
list = new List<Timer> (1024);
InitScheduler ();
}
public void Remove (Timer timer)
{
// We do not keep brand new items or those with no due time.
if (timer.next_run == 0 || timer.next_run == Int64.MaxValue)
return;
lock (this) {
// If this is the next item due (index = 0), the scheduler will wake up and find nothing.
// No need to Pulse ()
@@ -305,92 +309,51 @@ namespace System.Threading
public void Change (Timer timer, long new_next_run)
{
if (timer.is_dead)
timer.is_dead = false;
bool wake = false;
lock (this) {
InternalRemove (timer);
if (new_next_run == Int64.MaxValue) {
timer.next_run = new_next_run;
return;
}
needReSort = true;
if (!timer.disposed) {
// We should only change next_run after removing and before adding
if (!timer.is_added) {
timer.next_run = new_next_run;
Add (timer);
// If this timer is next in line, wake up the scheduler
wake = (list.GetByIndex (0) == timer);
Add(timer);
wake = current_next_run > new_next_run;
} else {
if (new_next_run == Int64.MaxValue) {
timer.next_run = new_next_run;
InternalRemove (timer);
return;
}
if (!timer.disposed) {
// We should only change next_run after removing and before adding
timer.next_run = new_next_run;
// FIXME
wake = current_next_run > new_next_run;
}
}
}
if (wake)
WakeupScheduler();
}
// lock held by caller
int FindByDueTime (long nr)
{
int min = 0;
int max = list.Count - 1;
if (max < 0)
return -1;
if (max < 20) {
while (min <= max) {
Timer t = (Timer) list.GetByIndex (min);
if (t.next_run == nr)
return min;
if (t.next_run > nr)
return -1;
min++;
}
return -1;
}
while (min <= max) {
int half = min + ((max - min) >> 1);
Timer t = (Timer) list.GetByIndex (half);
if (nr == t.next_run)
return half;
if (nr > t.next_run)
min = half + 1;
else
max = half - 1;
}
return -1;
}
// This should be the only caller to list.Add!
void Add (Timer timer)
{
// Make sure there are no collisions (10000 ticks == 1ms, so we should be safe here)
// Do not use list.IndexOfKey here. See bug #648130
int idx = FindByDueTime (timer.next_run);
if (idx != -1) {
bool up = (Int64.MaxValue - timer.next_run) > 20000 ? true : false;
while (true) {
idx++;
if (up)
timer.next_run++;
else
timer.next_run--;
if (idx >= list.Count)
break;
Timer t2 = (Timer) list.GetByIndex (idx);
if (t2.next_run != timer.next_run)
break;
}
}
list.Add (timer, timer);
timer.is_added = true;
needReSort = true;
list.Add (timer);
if (list.Count == 1)
WakeupScheduler();
//PrintList ();
}
int InternalRemove (Timer timer)
void InternalRemove (Timer timer)
{
int idx = list.IndexOfKey (timer);
if (idx >= 0)
list.RemoveAt (idx);
return idx;
timer.is_dead = true;
needReSort = true;
}
static void TimerCB (object o)
@@ -399,53 +362,71 @@ namespace System.Threading
timer.callback (timer.state);
}
int RunSchedulerLoop (List<Timer> new_time) {
void FireTimer (Timer timer) {
long period = timer.period_ms;
long due_time = timer.due_time_ms;
bool no_more = (period == -1 || ((period == 0 || period == Timeout.Infinite) && due_time != Timeout.Infinite));
if (no_more) {
timer.next_run = Int64.MaxValue;
timer.is_dead = true;
} else {
timer.next_run = GetTimeMonotonic () + TimeSpan.TicksPerMillisecond * timer.period_ms;
timer.is_dead = false;
}
ThreadPool.UnsafeQueueUserWorkItem (TimerCB, timer);
}
int RunSchedulerLoop () {
int ms_wait = -1;
int i;
int count = list.Count;
long ticks = GetTimeMonotonic ();
var comparer = new TimerComparer();
for (i = 0; i < count; i++) {
Timer timer = (Timer) list.GetByIndex (i);
if (timer.next_run > ticks)
break;
list.RemoveAt (i);
count--;
i--;
ThreadPool.UnsafeQueueUserWorkItem (TimerCB, timer);
long period = timer.period_ms;
long due_time = timer.due_time_ms;
bool no_more = (period == -1 || ((period == 0 || period == Timeout.Infinite) && due_time != Timeout.Infinite));
if (no_more) {
timer.next_run = Int64.MaxValue;
} else {
timer.next_run = GetTimeMonotonic () + TimeSpan.TicksPerMillisecond * timer.period_ms;
new_time.Add (timer);
}
if (needReSort) {
list.Sort(comparer);
needReSort = false;
}
// Reschedule timers with a new due time
count = new_time.Count;
for (i = 0; i < count; i++) {
Timer timer = new_time [i];
Add (timer);
}
new_time.Clear ();
ShrinkIfNeeded (new_time, 512);
// Shrink the list
int capacity = list.Capacity;
count = list.Count;
if (capacity > 1024 && count > 0 && (capacity / count) > 3)
list.Capacity = count * 2;
long min_next_run = Int64.MaxValue;
if (list.Count > 0)
min_next_run = ((Timer) list.GetByIndex (0)).next_run;
for (i = 0; i < list.Count; i++) {
Timer timer = list[i];
if (timer.is_dead)
continue;
if (timer.next_run <= ticks) {
FireTimer(timer);
}
min_next_run = Math.Min(min_next_run, timer.next_run);
if ((timer.next_run > ticks) && (timer.next_run < Int64.MaxValue))
timer.is_dead = false;
}
for (i = 0; i < list.Count; i++) {
Timer timer = list[i];
if (!timer.is_dead)
continue;
timer.is_added = false;
needReSort = true;
list[i] = list[list.Count - 1];
i--;
list.RemoveAt(list.Count - 1);
if (list.Count == 0)
break;
}
if (needReSort) {
list.Sort(comparer);
needReSort = false;
}
//PrintList ();
ms_wait = -1;
current_next_run = min_next_run;
if (min_next_run != Int64.MaxValue) {
long diff = (min_next_run - GetTimeMonotonic ()) / TimeSpan.TicksPerMillisecond;
if (diff > Int32.MaxValue)
@@ -459,14 +440,6 @@ namespace System.Threading
return ms_wait;
}
void ShrinkIfNeeded (List<Timer> list, int initial)
{
int capacity = list.Capacity;
int count = list.Count;
if (capacity > initial && count > 0 && (capacity / count) > 3)
list.Capacity = count * 2;
}
/*
void PrintList ()
{

View File

@@ -31,8 +31,9 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
#if !DISABLE_REMOTING
using System.Runtime.Remoting.Contexts;
using System.Security.Permissions;
#endif
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
@@ -41,7 +42,6 @@ namespace System.Threading
{
[StructLayout (LayoutKind.Sequential)]
public abstract partial class WaitHandle
: MarshalByRefObject, IDisposable
{
protected static readonly IntPtr InvalidHandle = (IntPtr) (-1);