You've already forked linux-packaging-mono
Imported Upstream version 4.8.0.309
Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
parent
ee1447783b
commit
94b2861243
@@ -155,7 +155,14 @@ namespace System
|
||||
if (PinnableBufferCacheEventSource.Log.IsEnabled())
|
||||
PinnableBufferCacheEventSource.Log.FreeBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(buffer), buffer.GetHashCode(), m_FreeList.Count);
|
||||
|
||||
|
||||
if(buffer == null)
|
||||
{
|
||||
if (PinnableBufferCacheEventSource.Log.IsEnabled())
|
||||
PinnableBufferCacheEventSource.Log.FreeBufferNull(m_CacheName, m_FreeList.Count);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// After we've done 3 gen1 GCs, assume that all buffers have aged into gen2 on the free path.
|
||||
if ((m_gen1CountAtLastRestock + 3) > GC.CollectionCount(GC.MaxGeneration - 1))
|
||||
{
|
||||
@@ -567,6 +574,7 @@ namespace System
|
||||
public void AllocateBufferAged(string cacheName, int agedCount) {}
|
||||
public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) {}
|
||||
public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) {}
|
||||
public void FreeBufferNull(string cacheName, int freeCountBefore) { }
|
||||
public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) {}
|
||||
public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) {}
|
||||
public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) {}
|
||||
@@ -643,6 +651,8 @@ namespace System
|
||||
public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) { if (IsEnabled()) WriteEvent(20, cacheName, promotedToFreeListCount, heldBackCount); }
|
||||
[Event(21)]
|
||||
public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { if (IsEnabled()) WriteEvent(21, cacheName, freeListCount, gen0BuffersInFreeList); }
|
||||
[Event(22)]
|
||||
public void FreeBufferNull(string cacheName, int freeCountBefore) { if(IsEnabled()) WriteEvent(22, cacheName, freeCountBefore); }
|
||||
|
||||
|
||||
static internal ulong AddressOf(object obj)
|
||||
|
||||
@@ -1 +1 @@
|
||||
9c2df18a2daf5d191612169f1bcc5d0cb9f10b82
|
||||
1bf3586fe471a184fd2979557e4ed976454224d7
|
||||
@@ -18,8 +18,7 @@ namespace System
|
||||
HasLookedForOverride = 0x4,
|
||||
UnknownValue = 0x8 // Has no default and could not find an override
|
||||
}
|
||||
private static Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
|
||||
private static readonly object s_syncLock = new object();
|
||||
private static readonly Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
|
||||
|
||||
public static string BaseDirectory
|
||||
{
|
||||
@@ -166,11 +165,12 @@ namespace System
|
||||
if (switchName.Length == 0)
|
||||
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName");
|
||||
|
||||
lock (s_syncLock)
|
||||
SwitchValueState switchValue = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
|
||||
| SwitchValueState.HasLookedForOverride;
|
||||
lock (s_switchMap)
|
||||
{
|
||||
// Store the new value and the fact that we checked in the dictionary
|
||||
s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
|
||||
| SwitchValueState.HasLookedForOverride;
|
||||
s_switchMap[switchName] = switchValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// ==++==
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
@@ -13,8 +13,11 @@ namespace System
|
||||
internal static readonly string SwitchNoAsyncCurrentCulture = "Switch.System.Globalization.NoAsyncCurrentCulture";
|
||||
internal static readonly string SwitchThrowExceptionIfDisposedCancellationTokenSource = "Switch.System.Threading.ThrowExceptionIfDisposedCancellationTokenSource";
|
||||
internal static readonly string SwitchPreserveEventListnerObjectIdentity = "Switch.System.Diagnostics.EventSource.PreserveEventListnerObjectIdentity";
|
||||
internal static readonly string SwitchUseLegacyPathHandling = "Switch.System.IO.UseLegacyPathHandling";
|
||||
internal static readonly string SwitchBlockLongPaths = "Switch.System.IO.BlockLongPaths";
|
||||
internal static readonly string SwitchSetActorAsReferenceWhenCopyingClaimsIdentity = "Switch.System.Security.ClaimsIdentity.SetActorAsReferenceWhenCopyingClaimsIdentity";
|
||||
|
||||
|
||||
|
||||
// This is a partial method. Platforms can provide an implementation of it that will set override values
|
||||
// from whatever mechanism is available on that platform. If no implementation is provided, the compiler is going to remove the calls
|
||||
// to it from the code
|
||||
@@ -41,6 +44,14 @@ namespace System
|
||||
AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
|
||||
AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
|
||||
}
|
||||
|
||||
if (version <= 40601)
|
||||
{
|
||||
AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true);
|
||||
AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true);
|
||||
AppContext.DefineSwitchDefault(SwitchSetActorAsReferenceWhenCopyingClaimsIdentity, true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "WindowsPhone":
|
||||
@@ -50,6 +61,8 @@ namespace System
|
||||
{
|
||||
AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
|
||||
AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
|
||||
AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true);
|
||||
AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
|
||||
// There are cases where we have multiple assemblies that are going to import this file and
|
||||
// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning
|
||||
// that the type is found both in the source and in a referenced assembly. The compiler will prefer
|
||||
// the version of the type defined in the source
|
||||
//
|
||||
// In order to disable the warning for this type we are disabling this warning for this entire file.
|
||||
#pragma warning disable 436
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -167,3 +176,5 @@ namespace System
|
||||
static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 436
|
||||
|
||||
@@ -41,6 +41,48 @@ namespace System
|
||||
}
|
||||
}
|
||||
|
||||
private static int _useLegacyPathHandling;
|
||||
|
||||
/// <summary>
|
||||
/// Use legacy path normalization logic and blocking of extended syntax.
|
||||
/// </summary>
|
||||
public static bool UseLegacyPathHandling
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return GetCachedSwitchValue(AppContextDefaultValues.SwitchUseLegacyPathHandling, ref _useLegacyPathHandling);
|
||||
}
|
||||
}
|
||||
|
||||
private static int _blockLongPaths;
|
||||
|
||||
/// <summary>
|
||||
/// Throw PathTooLongException for paths greater than MAX_PATH or directories greater than 248 (as per CreateDirectory Win32 limitations)
|
||||
/// </summary>
|
||||
public static bool BlockLongPaths
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return GetCachedSwitchValue(AppContextDefaultValues.SwitchBlockLongPaths, ref _blockLongPaths);
|
||||
}
|
||||
}
|
||||
|
||||
private static int _cloneActor;
|
||||
|
||||
/// <summary>
|
||||
/// When copying a ClaimsIdentity.Actor this switch controls whether ClaimsIdentity.Actor should be set as a reference or the result of Actor.Clone()
|
||||
/// </summary>
|
||||
public static bool SetActorAsReferenceWhenCopyingClaimsIdentity
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return GetCachedSwitchValue(AppContextDefaultValues.SwitchSetActorAsReferenceWhenCopyingClaimsIdentity, ref _cloneActor);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Implementation details
|
||||
//
|
||||
|
||||
@@ -318,17 +318,23 @@ namespace System {
|
||||
}
|
||||
}
|
||||
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
[ResourceConsumption(ResourceScope.Machine)]
|
||||
private String NormalizePath(String path, bool useAppBase)
|
||||
[System.Security.SecuritySafeCritical]
|
||||
private string NormalizePath(string path, bool useAppBase)
|
||||
{
|
||||
if(path == null)
|
||||
return null;
|
||||
|
||||
// If we add very long file name support ("\\?\") to the Path class then this is unnecesary,
|
||||
// but we do not plan on doing this for now.
|
||||
|
||||
// Long path checks can be quirked, and as loading default quirks too early in the setup of an AppDomain is risky
|
||||
// we'll avoid checking path lengths- we'll still fail at MAX_PATH later if we're !useAppBase when we call Path's
|
||||
// NormalizePath.
|
||||
if (!useAppBase)
|
||||
path = System.Security.Util.URLString.PreProcessForExtendedPathRemoval(path, false);
|
||||
path = System.Security.Util.URLString.PreProcessForExtendedPathRemoval(
|
||||
checkPathLength: false,
|
||||
url: path,
|
||||
isFileUrl: false);
|
||||
|
||||
int len = path.Length;
|
||||
if (len == 0)
|
||||
@@ -417,10 +423,10 @@ namespace System {
|
||||
|
||||
if (localPath)
|
||||
{
|
||||
|
||||
if (useAppBase &&
|
||||
( (len == 1) || (path[1] != ':') )) {
|
||||
String appBase = Value[(int) LoaderInformation.ApplicationBaseValue];
|
||||
((len == 1) || (path[1] != ':')))
|
||||
{
|
||||
String appBase = Value[(int)LoaderInformation.ApplicationBaseValue];
|
||||
|
||||
if ((appBase == null) || (appBase.Length == 0))
|
||||
throw new MemberAccessException(Environment.GetResourceString("AppDomain_AppBaseNotSet"));
|
||||
@@ -429,7 +435,9 @@ namespace System {
|
||||
|
||||
bool slash = false;
|
||||
if ((path[0] == '/') || (path[0] == '\\')) {
|
||||
String pathRoot = Path.GetPathRoot(appBase);
|
||||
// Emulate Path.GetPathRoot without hitting code paths that check quirks
|
||||
string pathRoot = AppDomain.NormalizePath(appBase, fullCheck: false);
|
||||
pathRoot = pathRoot.Substring(0, System.IO.PathInternal.GetRootLength(pathRoot));
|
||||
if (pathRoot.Length == 0) { // URL
|
||||
int index = appBase.IndexOf(":/", StringComparison.Ordinal);
|
||||
if (index == -1)
|
||||
@@ -439,11 +447,11 @@ namespace System {
|
||||
int urlLen = appBase.Length;
|
||||
for (index += 1;
|
||||
(index < urlLen) && ((appBase[index] == '/') || (appBase[index] == '\\'));
|
||||
index++);
|
||||
index++) ;
|
||||
|
||||
// Now find the next slash to get domain name
|
||||
for(; (index < urlLen) && (appBase[index] != '/') && (appBase[index] != '\\');
|
||||
index++);
|
||||
for (; (index < urlLen) && (appBase[index] != '/') && (appBase[index] != '\\');
|
||||
index++) ;
|
||||
|
||||
pathRoot = appBase.Substring(0, index);
|
||||
}
|
||||
@@ -472,7 +480,9 @@ namespace System {
|
||||
path = StringBuilderCache.GetStringAndRelease(result);
|
||||
}
|
||||
else
|
||||
path = Path.GetFullPathInternal(path);
|
||||
{
|
||||
path = AppDomain.NormalizePath(path, fullCheck: true);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
@@ -792,20 +802,32 @@ namespace System {
|
||||
[ResourceConsumption(ResourceScope.Machine)]
|
||||
private String VerifyDir(String dir, bool normalize)
|
||||
{
|
||||
if (dir != null) {
|
||||
if (dir != null)
|
||||
{
|
||||
if (dir.Length == 0)
|
||||
{
|
||||
dir = null;
|
||||
else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (normalize)
|
||||
dir = NormalizePath(dir, true);
|
||||
|
||||
// The only way AppDomainSetup is exposed in coreclr is through the AppDomainManager
|
||||
// and the AppDomainManager is a SecurityCritical type. Also, all callers of callstacks
|
||||
// leading from VerifyDir are SecurityCritical. So we can remove the Demand because
|
||||
// we have validated that all callers are SecurityCritical
|
||||
// The only way AppDomainSetup is exposed in coreclr is through the AppDomainManager
|
||||
// and the AppDomainManager is a SecurityCritical type. Also, all callers of callstacks
|
||||
// leading from VerifyDir are SecurityCritical. So we can remove the Demand because
|
||||
// we have validated that all callers are SecurityCritical
|
||||
#if !FEATURE_CORECLR
|
||||
if (IsFilePath(dir))
|
||||
new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dir ).Demand();
|
||||
{
|
||||
// If we've already normalized we don't need to do it again, and can avoid hitting
|
||||
// quirks in FileIOPermission.
|
||||
new FileIOPermission(
|
||||
access: FileIOPermissionAccess.PathDiscovery,
|
||||
pathList: new string[] { dir },
|
||||
checkForDuplicates: false,
|
||||
needFullPath: false).Demand();
|
||||
}
|
||||
#endif // !FEATURE_CORECLR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
0d7719d224a5cc564d4059a538c91201946c6082
|
||||
2a704e83006fa15410f41e5e15bbe8ae7ddd0a4f
|
||||
@@ -372,7 +372,7 @@ namespace System {
|
||||
// Converts an array of bytes into a String.
|
||||
public static String ToString (byte[] value, int startIndex, int length) {
|
||||
if (value == null) {
|
||||
throw new ArgumentNullException("byteArray");
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
|
||||
if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) { // Don't throw for a 0 length array.
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace System {
|
||||
using System.Security.Permissions;
|
||||
[Serializable]
|
||||
[System.Runtime.InteropServices.ComVisible(true)]
|
||||
#if FEATURE_REMOTING
|
||||
#if FEATURE_REMOTING || MONO
|
||||
public abstract class ContextBoundObject : MarshalByRefObject {
|
||||
#else // FEATURE_REMOTING
|
||||
public abstract class ContextBoundObject {
|
||||
|
||||
@@ -79,18 +79,18 @@ namespace System.Deployment.Internal.Isolation.Manifest {
|
||||
|
||||
[ResourceExposure(ResourceScope.Machine)]
|
||||
[ResourceConsumption(ResourceScope.Machine)]
|
||||
internal static string GetEntryPointFullPath (ActivationContext activationContext) {
|
||||
internal static string GetEntryPointFullPath (ActivationContext activationContext)
|
||||
{
|
||||
string file, parameters;
|
||||
GetEntryPoint(activationContext, out file, out parameters);
|
||||
|
||||
if (!String.IsNullOrEmpty(file)) {
|
||||
if (!string.IsNullOrEmpty(file))
|
||||
{
|
||||
string directoryName = activationContext.ApplicationDirectory;
|
||||
if (directoryName == null || directoryName.Length == 0) {
|
||||
if (directoryName == null || directoryName.Length == 0)
|
||||
{
|
||||
// If we were passed a relative path, assume the app base is the current working directory
|
||||
StringBuilder sb = new StringBuilder(Path.MAX_PATH + 1);
|
||||
if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0)
|
||||
System.IO.__Error.WinIOError();
|
||||
directoryName = sb.ToString();
|
||||
directoryName = Directory.UnsafeGetCurrentDirectory();
|
||||
}
|
||||
|
||||
file = Path.Combine(directoryName, file);
|
||||
|
||||
@@ -833,6 +833,15 @@ namespace System.Diagnostics.Tracing
|
||||
{
|
||||
collector.AddBinary(value);
|
||||
}
|
||||
|
||||
public override object GetData(object value)
|
||||
{
|
||||
object val = base.GetData(value);
|
||||
if (null == val)
|
||||
val = "";
|
||||
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -460,6 +460,7 @@ namespace System.Diagnostics.Tracing
|
||||
}
|
||||
|
||||
this.WriteEventRaw(
|
||||
eventName,
|
||||
ref descriptor,
|
||||
activityID,
|
||||
childActivityID,
|
||||
@@ -564,6 +565,7 @@ namespace System.Diagnostics.Tracing
|
||||
}
|
||||
|
||||
this.WriteEventRaw(
|
||||
eventName,
|
||||
ref descriptor,
|
||||
activityID,
|
||||
childActivityID,
|
||||
@@ -646,6 +648,7 @@ namespace System.Diagnostics.Tracing
|
||||
eventTypes.typeInfo.WriteData(TraceLoggingDataCollector.Instance, ref data);
|
||||
|
||||
this.WriteEventRaw(
|
||||
eventName,
|
||||
ref descriptor,
|
||||
pActivityId,
|
||||
pRelatedActivityId,
|
||||
@@ -665,7 +668,7 @@ namespace System.Diagnostics.Tracing
|
||||
if (ex is EventSourceException)
|
||||
throw;
|
||||
else
|
||||
ThrowEventSourceException(ex);
|
||||
ThrowEventSourceException(eventName, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -679,7 +682,7 @@ namespace System.Diagnostics.Tracing
|
||||
if (ex is EventSourceException)
|
||||
throw;
|
||||
else
|
||||
ThrowEventSourceException(ex);
|
||||
ThrowEventSourceException(eventName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,7 +706,7 @@ namespace System.Diagnostics.Tracing
|
||||
eventCallbackArgs.PayloadNames = new ReadOnlyCollection<string>((IList<string>)payload.Keys);
|
||||
}
|
||||
|
||||
DisptachToAllListeners(-1, pActivityId, eventCallbackArgs);
|
||||
DispatchToAllListeners(-1, pActivityId, eventCallbackArgs);
|
||||
}
|
||||
|
||||
#if !ES_BUILD_PCL
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace System.Diagnostics.Tracing
|
||||
var newGroup = new FieldMetadata(
|
||||
name,
|
||||
TraceLoggingDataType.Struct,
|
||||
0,
|
||||
this.Tags,
|
||||
this.BeginningBufferedArray);
|
||||
this.AddField(newGroup);
|
||||
result = new TraceLoggingMetadataCollector(this, newGroup);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#if !ES_BUILD_AGAINST_DOTNET_V35
|
||||
using Contract = System.Diagnostics.Contracts.Contract;
|
||||
#else
|
||||
@@ -11,15 +9,16 @@ using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
#else
|
||||
using System.Threading.Tasks;
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Tracks activities. This is meant to be a singledon (accessed by the ActivityTracer.Instance static property)
|
||||
/// Tracks activities. This is meant to be a singleton (accessed by the ActivityTracer.Instance static property)
|
||||
///
|
||||
/// Logically this is simply holds the m_current variable that holds the async local that holds the current ActivityInfo
|
||||
/// An ActivityInfo is represents a actvity (which knows its creator and thus knows its path).
|
||||
/// An ActivityInfo is represents a activity (which knows its creator and thus knows its path).
|
||||
///
|
||||
/// Most of the magic is in the async local (it gets copied to new tasks)
|
||||
///
|
||||
@@ -39,7 +38,7 @@ namespace System.Diagnostics.Tracing
|
||||
/// On any normal event log the event with activityTracker.CurrentActivityId
|
||||
/// </summary>
|
||||
internal class ActivityTracker
|
||||
{
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Called on work item begins. The activity name = providerName + activityName without 'Start' suffix.
|
||||
@@ -55,15 +54,32 @@ namespace System.Diagnostics.Tracing
|
||||
public void OnStart(string providerName, string activityName, int task, ref Guid activityId, ref Guid relatedActivityId, EventActivityOptions options)
|
||||
{
|
||||
if (m_current == null) // We are not enabled
|
||||
return;
|
||||
{
|
||||
// We used to rely on the TPL provider turning us on, but that has the disadvantage that you don't get Start-Stop tracking
|
||||
// until you use Tasks for the first time (which you may never do). Thus we change it to pull rather tan push for whether
|
||||
// we are enabled.
|
||||
if (m_checkedForEnable)
|
||||
return;
|
||||
m_checkedForEnable = true;
|
||||
#if ES_BUILD_STANDALONE
|
||||
Enable(); // Enable it unconditionally.
|
||||
#else
|
||||
if (System.Threading.Tasks.TplEtwProvider.Log.IsEnabled(EventLevel.Informational, System.Threading.Tasks.TplEtwProvider.Keywords.TasksFlowActivityIds))
|
||||
Enable();
|
||||
#endif
|
||||
if(m_current == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Contract.Assert((options & EventActivityOptions.Disable) == 0);
|
||||
|
||||
var currentActivity = m_current.Value;
|
||||
var fullActivityName = NormalizeActivityName(providerName, activityName, task);
|
||||
|
||||
|
||||
var etwLog = TplEtwProvider.Log;
|
||||
if (etwLog.Debug)
|
||||
if (etwLog.Debug)
|
||||
{
|
||||
etwLog.DebugFacilityMessage("OnStartEnter", fullActivityName);
|
||||
etwLog.DebugFacilityMessage("OnStartEnterActivityState", ActivityInfo.LiveActivities(currentActivity));
|
||||
@@ -100,17 +116,17 @@ namespace System.Diagnostics.Tracing
|
||||
else
|
||||
id = Interlocked.Increment(ref currentActivity.m_lastChildID);
|
||||
|
||||
// Remember the previous ID so we can log it
|
||||
relatedActivityId = currentActivity != null ? currentActivity.ActivityId : Guid.Empty;
|
||||
// The previous ID is my 'causer' and becomes my related activity ID
|
||||
relatedActivityId = EventSource.CurrentThreadActivityId;
|
||||
|
||||
// Add to the list of started but not stopped activities.
|
||||
ActivityInfo newActivity = new ActivityInfo(fullActivityName, id, currentActivity, options);
|
||||
ActivityInfo newActivity = new ActivityInfo(fullActivityName, id, currentActivity, relatedActivityId, options);
|
||||
m_current.Value = newActivity;
|
||||
|
||||
// Remember the current ID so we can log it
|
||||
activityId = newActivity.ActivityId;
|
||||
|
||||
if (etwLog.Debug)
|
||||
if (etwLog.Debug)
|
||||
{
|
||||
etwLog.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(newActivity));
|
||||
etwLog.DebugFacilityMessage1("OnStartRet", activityId.ToString(), relatedActivityId.ToString());
|
||||
@@ -119,7 +135,7 @@ namespace System.Diagnostics.Tracing
|
||||
|
||||
/// <summary>
|
||||
/// Called when a work item stops. The activity name = providerName + activityName without 'Stop' suffix.
|
||||
/// It updates CurrentActivityId to track this fact. The Stop event associated with stop should log the ActivityID associated with the event.
|
||||
/// It updates m_current variable to track this fact. The Stop event associated with stop should log the ActivityID associated with the event.
|
||||
///
|
||||
/// If activity tracing is not on, then activityId and relatedActivityId are not set
|
||||
/// </summary>
|
||||
@@ -131,13 +147,13 @@ namespace System.Diagnostics.Tracing
|
||||
var fullActivityName = NormalizeActivityName(providerName, activityName, task);
|
||||
|
||||
var etwLog = TplEtwProvider.Log;
|
||||
if (etwLog.Debug)
|
||||
if (etwLog.Debug)
|
||||
{
|
||||
etwLog.DebugFacilityMessage("OnStopEnter", fullActivityName);
|
||||
etwLog.DebugFacilityMessage("OnStopEnterActivityState", ActivityInfo.LiveActivities(m_current.Value));
|
||||
}
|
||||
|
||||
for (; ;) // This is a retry loop.
|
||||
for (; ; ) // This is a retry loop.
|
||||
{
|
||||
ActivityInfo currentActivity = m_current.Value;
|
||||
ActivityInfo newCurrentActivity = null; // if we have seen any live activities (orphans), at he first one we have seen.
|
||||
@@ -193,7 +209,7 @@ namespace System.Diagnostics.Tracing
|
||||
|
||||
m_current.Value = newCurrentActivity;
|
||||
|
||||
if (etwLog.Debug)
|
||||
if (etwLog.Debug)
|
||||
{
|
||||
etwLog.DebugFacilityMessage("OnStopRetActivityState", ActivityInfo.LiveActivities(newCurrentActivity));
|
||||
etwLog.DebugFacilityMessage("OnStopRet", activityId.ToString());
|
||||
@@ -210,12 +226,12 @@ namespace System.Diagnostics.Tracing
|
||||
[System.Security.SecuritySafeCritical]
|
||||
public void Enable()
|
||||
{
|
||||
if (m_current == null)
|
||||
if (m_current == null)
|
||||
{
|
||||
m_current = new AsyncLocal<ActivityInfo>(ActivityChanging);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// An activity tracker is a singleton, this is how you get the one and only instance.
|
||||
/// </summary>
|
||||
@@ -263,24 +279,25 @@ namespace System.Diagnostics.Tracing
|
||||
|
||||
// *******************************************************************************
|
||||
/// <summary>
|
||||
/// An ActivityInfo repesents a particular activity. It is almost read-only the only
|
||||
/// An ActivityInfo represents a particular activity. It is almost read-only. The only
|
||||
/// fields that change after creation are
|
||||
/// m_lastChildID - used to generate unique IDs for the children activities and for the most part can be ignored.
|
||||
/// m_stopped - indicates that this activity is dead
|
||||
/// This read-only ness is important because an activity's m_creator chain forms the
|
||||
/// This read-only-ness is important because an activity's m_creator chain forms the
|
||||
/// 'Path of creation' for the activity (which is also its unique ID) but is also used as
|
||||
/// the 'list of live parents' which indicate of those ancestors, which are alive (if they
|
||||
/// are not marked dead they are alive).
|
||||
/// </summary>
|
||||
private class ActivityInfo
|
||||
{
|
||||
public ActivityInfo(string name, long uniqueId, ActivityInfo creator, EventActivityOptions options)
|
||||
public ActivityInfo(string name, long uniqueId, ActivityInfo creator, Guid activityIDToRestore, EventActivityOptions options)
|
||||
{
|
||||
m_name = name;
|
||||
m_eventOptions = options;
|
||||
m_creator = creator;
|
||||
m_uniqueId = uniqueId;
|
||||
m_level = creator != null ? creator.m_level + 1 : 0;
|
||||
m_activityIdToRestore = activityIDToRestore;
|
||||
|
||||
// Create a nice GUID that encodes the chain of activities that started this one.
|
||||
CreateActivityPathGuid(out m_guid, out m_activityPathGuidOffset);
|
||||
@@ -294,19 +311,19 @@ namespace System.Diagnostics.Tracing
|
||||
}
|
||||
}
|
||||
|
||||
public static string Path(ActivityInfo activityInfo)
|
||||
public static string Path(ActivityInfo activityInfo)
|
||||
{
|
||||
if (activityInfo == null)
|
||||
return("");
|
||||
return ("");
|
||||
return Path(activityInfo.m_creator) + "/" + activityInfo.m_uniqueId;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
public override string ToString()
|
||||
{
|
||||
string dead = "";
|
||||
if (m_stopped != 0)
|
||||
dead = ",DEAD";
|
||||
return m_name + "(" + Path(this) + dead + ")";
|
||||
dead = ",DEAD";
|
||||
return m_name + "(" + Path(this) + dead + ")";
|
||||
}
|
||||
|
||||
public static string LiveActivities(ActivityInfo list)
|
||||
@@ -331,10 +348,10 @@ namespace System.Diagnostics.Tracing
|
||||
/// (rooted in an activity that predates activity tracking.
|
||||
///
|
||||
/// We wish to encode this path in the Guid to the extent that we can. Many of the paths have
|
||||
/// many small numbers in them and we take advatage of this in the encoding to output as long
|
||||
/// many small numbers in them and we take advantage of this in the encoding to output as long
|
||||
/// a path in the GUID as possible.
|
||||
///
|
||||
/// Because of the possiblility of GUID collistion, we only use 96 of the 128 bits of the GUID
|
||||
/// Because of the possibility of GUID collision, we only use 96 of the 128 bits of the GUID
|
||||
/// for encoding the path. The last 32 bits are a simple checksum (and random number) that
|
||||
/// identifies this as using the convention defined here.
|
||||
///
|
||||
@@ -347,7 +364,7 @@ namespace System.Diagnostics.Tracing
|
||||
[System.Security.SecuritySafeCritical]
|
||||
private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset)
|
||||
{
|
||||
fixed (Guid* outPtr = &idRet)
|
||||
fixed (Guid* outPtr = &idRet)
|
||||
{
|
||||
int activityPathGuidOffsetStart = 0;
|
||||
if (m_creator != null)
|
||||
@@ -355,13 +372,18 @@ namespace System.Diagnostics.Tracing
|
||||
activityPathGuidOffsetStart = m_creator.m_activityPathGuidOffset;
|
||||
idRet = m_creator.m_guid;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// We start with the appdomain number to make this unique among appdomains.
|
||||
activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint) System.Threading.Thread.GetDomainID());
|
||||
//
|
||||
int appDomainID = 0;
|
||||
#if !ES_BUILD_PCL
|
||||
appDomainID = System.Threading.Thread.GetDomainID();
|
||||
#endif
|
||||
// We start with the appdomain number to make this unique among appdomains.
|
||||
activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)appDomainID);
|
||||
}
|
||||
|
||||
activityPathGuidOffset = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint) m_uniqueId);
|
||||
activityPathGuidOffset = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)m_uniqueId);
|
||||
|
||||
|
||||
// If the path does not fit, Make a GUID by incrementing rather than as a path, keeping as much of the path as possible
|
||||
@@ -372,19 +394,19 @@ namespace System.Diagnostics.Tracing
|
||||
|
||||
/// <summary>
|
||||
/// If we can't fit the activity Path into the GUID we come here. What we do is simply
|
||||
/// generate a 4 byte number (s_nextOverflowId). Then look for an anscesor that has
|
||||
/// generate a 4 byte number (s_nextOverflowId). Then look for an ancestor that has
|
||||
/// sufficient space for this ID. By doing this, we preserve the fact that this activity
|
||||
/// is a child (of unknown depth) from that ancestor.
|
||||
/// </summary>
|
||||
[System.Security.SecurityCritical]
|
||||
private unsafe void CreateOverflowGuid(Guid* outPtr)
|
||||
{
|
||||
// Seach backwards for an ancestor that has sufficient space to put the ID.
|
||||
for(ActivityInfo ancestor = m_creator; ancestor != null; ancestor = ancestor.m_creator)
|
||||
// Search backwards for an ancestor that has sufficient space to put the ID.
|
||||
for (ActivityInfo ancestor = m_creator; ancestor != null; ancestor = ancestor.m_creator)
|
||||
{
|
||||
if (ancestor.m_activityPathGuidOffset <= 10) // we need at least 2 bytes.
|
||||
{
|
||||
uint id = (uint) Interlocked.Increment(ref ancestor.m_lastChildID); // Get a unique ID
|
||||
uint id = unchecked((uint)Interlocked.Increment(ref ancestor.m_lastChildID)); // Get a unique ID
|
||||
// Try to put the ID into the GUID
|
||||
*outPtr = ancestor.m_guid;
|
||||
int endId = AddIdToGuid(outPtr, ancestor.m_activityPathGuidOffset, id, true);
|
||||
@@ -397,8 +419,8 @@ namespace System.Diagnostics.Tracing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The encoding for a list of numbers used to make Activity Guids. Basically
|
||||
/// we operate on nibbles (which are nice becase they show up as hex digits). The
|
||||
/// The encoding for a list of numbers used to make Activity GUIDs. Basically
|
||||
/// we operate on nibbles (which are nice because they show up as hex digits). The
|
||||
/// list is ended with a end nibble (0) and depending on the nibble value (Below)
|
||||
/// the value is either encoded into nibble itself or it can spill over into the
|
||||
/// bytes that follow.
|
||||
@@ -409,18 +431,18 @@ namespace System.Diagnostics.Tracing
|
||||
LastImmediateValue = 0xA,
|
||||
|
||||
PrefixCode = 0xB, // all the 'long' encodings go here. If the next nibble is MultiByte1-4
|
||||
// than this is a 'overflow' id. Unlike the hierarchitcal IDs these are
|
||||
// allocated densly but don't tell you anything about nesting. we use
|
||||
// these when we run out of space in the GUID to store the path.
|
||||
// than this is a 'overflow' id. Unlike the hierarchical IDs these are
|
||||
// allocated densely but don't tell you anything about nesting. we use
|
||||
// these when we run out of space in the GUID to store the path.
|
||||
|
||||
MultiByte1 = 0xC, // 1 byte follows. If this Nibble is in the high bits, it the high bits of the number are stored in the low nibble.
|
||||
// commented out because the code does not explicitly reference the names (but they are logically defined).
|
||||
// MultiByte2 = 0xD, // 2 bytes follow (we don't bother with the nibble optimzation)
|
||||
// MultiByte3 = 0xE, // 3 bytes follow (we don't bother with the nibble optimzation)
|
||||
// MultiByte4 = 0xF, // 4 bytes follow (we don't bother with the nibble optimzation)
|
||||
// MultiByte2 = 0xD, // 2 bytes follow (we don't bother with the nibble optimization)
|
||||
// MultiByte3 = 0xE, // 3 bytes follow (we don't bother with the nibble optimization)
|
||||
// MultiByte4 = 0xF, // 4 bytes follow (we don't bother with the nibble optimization)
|
||||
}
|
||||
|
||||
/// Add the acivity id 'id' to the output Guid 'outPtr' starting at the offset 'whereToAddId'
|
||||
/// Add the activity id 'id' to the output Guid 'outPtr' starting at the offset 'whereToAddId'
|
||||
/// Thus if this number is 6 that is where 'id' will be added. This will return 13 (12
|
||||
/// is the maximum number of bytes that fit in a GUID) if the path did not fit.
|
||||
/// If 'overflow' is true, then the number is encoded as an 'overflow number (which has a
|
||||
@@ -450,9 +472,9 @@ namespace System.Diagnostics.Tracing
|
||||
{
|
||||
if (endPtr <= ptr + 2) // I need at least 2 bytes
|
||||
return 13;
|
||||
|
||||
|
||||
// Write out the prefix code nibble and the length nibble
|
||||
WriteNibble(ref ptr, endPtr, (uint) NumberListCodes.PrefixCode);
|
||||
WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.PrefixCode);
|
||||
}
|
||||
// The rest is the same for overflow and non-overflow case
|
||||
WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.MultiByte1 + (len - 1));
|
||||
@@ -460,7 +482,7 @@ namespace System.Diagnostics.Tracing
|
||||
// Do we have an odd nibble? If so flush it or use it for the 12 byte case.
|
||||
if (ptr < endPtr && *ptr != 0)
|
||||
{
|
||||
// If the value < 4096 we can use the nibble we are otherwise just outputing as padding.
|
||||
// If the value < 4096 we can use the nibble we are otherwise just outputting as padding.
|
||||
if (id < 4096)
|
||||
{
|
||||
// Indicate this is a 1 byte multicode with 4 high order bits in the lower nibble.
|
||||
@@ -471,7 +493,7 @@ namespace System.Diagnostics.Tracing
|
||||
}
|
||||
|
||||
// Write out the bytes.
|
||||
while(0 < len)
|
||||
while (0 < len)
|
||||
{
|
||||
if (endPtr <= ptr)
|
||||
{
|
||||
@@ -514,14 +536,15 @@ namespace System.Diagnostics.Tracing
|
||||
#endregion // CreateGuidForActivityPath
|
||||
|
||||
readonly internal string m_name; // The name used in the 'start' and 'stop' APIs to help match up
|
||||
readonly long m_uniqueId; // a small number that makes this activity unique among its siblings
|
||||
internal readonly Guid m_guid; // Activity Guid, it is bascially an encoding of the Path() (see CreateActivityPathGuid)
|
||||
readonly long m_uniqueId; // a small number that makes this activity unique among its siblings
|
||||
internal readonly Guid m_guid; // Activity Guid, it is basically an encoding of the Path() (see CreateActivityPathGuid)
|
||||
internal readonly int m_activityPathGuidOffset; // Keeps track of where in m_guid the causality path stops (used to generated child GUIDs)
|
||||
internal readonly int m_level; // current depth of the Path() of the activity (used to keep recursion under control)
|
||||
readonly internal EventActivityOptions m_eventOptions; // Options passed to start.
|
||||
internal long m_lastChildID; // used to create a unique ID for my children activities
|
||||
internal int m_stopped; // This work item has stopped
|
||||
readonly internal ActivityInfo m_creator; // My parent (creator). Forms the Path() for the activity.
|
||||
readonly internal Guid m_activityIdToRestore; // The Guid to restore after a stop.
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -530,26 +553,50 @@ namespace System.Diagnostics.Tracing
|
||||
// with m_current.ActivityID
|
||||
void ActivityChanging(AsyncLocalValueChangedArgs<ActivityInfo> args)
|
||||
{
|
||||
if (args.PreviousValue == args.CurrentValue)
|
||||
return;
|
||||
ActivityInfo cur = args.CurrentValue;
|
||||
ActivityInfo prev = args.PreviousValue;
|
||||
|
||||
if (args.CurrentValue != null)
|
||||
// Are we popping off a value? (we have a prev, and it creator is cur)
|
||||
// Then check if we should use the GUID at the time of the start event
|
||||
if (prev != null && prev.m_creator == cur)
|
||||
{
|
||||
// Allow subsequent activities inside this thread to automatically get the current activity ID.
|
||||
EventSource.SetCurrentThreadActivityId(args.CurrentValue.ActivityId);
|
||||
// If the saved activity ID is not the same as the creator activity
|
||||
// that takes precedence (it means someone explicitly did a SetActivityID)
|
||||
// Set it to that and get out
|
||||
if (cur == null || prev.m_activityIdToRestore != cur.ActivityId)
|
||||
{
|
||||
EventSource.SetCurrentThreadActivityId(prev.m_activityIdToRestore);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
EventSource.SetCurrentThreadActivityId(Guid.Empty);
|
||||
|
||||
// OK we did not have an explicit SetActivityID set. Then we should be
|
||||
// setting the activity to current ActivityInfo. However that activity
|
||||
// might be dead, in which case we should skip it, so we never set
|
||||
// the ID to dead things.
|
||||
while(cur != null)
|
||||
{
|
||||
// We found a live activity (typically the first time), set it to that.
|
||||
if (cur.m_stopped == 0)
|
||||
{
|
||||
EventSource.SetCurrentThreadActivityId(cur.ActivityId);
|
||||
return;
|
||||
}
|
||||
cur = cur.m_creator;
|
||||
}
|
||||
// we can get here if there is no information on our activity stack (everything is dead)
|
||||
// currently we do nothing, as that seems better than setting to Guid.Emtpy.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Async local variables have the propery that the are automatically copied whenever a task is created and used
|
||||
/// Async local variables have the properly that the are automatically copied whenever a task is created and used
|
||||
/// while that task is running. Thus m_current 'flows' to any task that is caused by the current thread that
|
||||
/// last set it.
|
||||
///
|
||||
/// This variable points a a linked list that represents all Activities that have started but have not stopped.
|
||||
/// </summary>
|
||||
AsyncLocal<ActivityInfo> m_current;
|
||||
bool m_checkedForEnable;
|
||||
|
||||
// Singleton
|
||||
private static ActivityTracker s_activityTrackerInstance = new ActivityTracker();
|
||||
@@ -557,8 +604,74 @@ namespace System.Diagnostics.Tracing
|
||||
// Used to create unique IDs at the top level. Not used for nested Ids (each activity has its own id generator)
|
||||
static long m_nextId = 0;
|
||||
private const ushort MAX_ACTIVITY_DEPTH = 100; // Limit maximum depth of activities to be tracked at 100.
|
||||
// This will avoid leaking memory in case of activities that are never stopped.
|
||||
// This will avoid leaking memory in case of activities that are never stopped.
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
/******************************** SUPPORT *****************************/
|
||||
/// <summary>
|
||||
/// This is supplied by the framework. It is has the semantics that the value is copied to any new Tasks that is created
|
||||
/// by the current task. Thus all causally related code gets this value. Note that reads and writes to this VARIABLE
|
||||
/// (not what it points it) to this does not need to be protected by locks because it is inherently thread local (you always
|
||||
/// only get your thread local copy which means that you never have ----s.
|
||||
/// </summary>
|
||||
///
|
||||
[EventSource(Name="Microsoft.Tasks.Nuget")]
|
||||
internal class TplEtwProvider : EventSource
|
||||
{
|
||||
public class Keywords
|
||||
{
|
||||
public const EventKeywords Debug = (EventKeywords) 1;
|
||||
}
|
||||
|
||||
public static TplEtwProvider Log = new TplEtwProvider();
|
||||
public bool Debug { get { return IsEnabled(EventLevel.Verbose, Keywords.Debug); } }
|
||||
|
||||
public void DebugFacilityMessage(string Facility, string Message) { WriteEvent(1, Facility, Message); }
|
||||
public void DebugFacilityMessage1(string Facility, string Message, string Arg) { WriteEvent(2, Facility, Message, Arg); }
|
||||
public void SetActivityId(Guid Id) { WriteEvent(3, Id); }
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ES_BUILD_AGAINST_DOTNET_V35 || ES_BUILD_PCL || NO_ASYNC_LOCAL
|
||||
|
||||
internal sealed class AsyncLocalValueChangedArgs<T>
|
||||
{
|
||||
public AsyncLocalValueChangedArgs()
|
||||
{
|
||||
}
|
||||
|
||||
public T PreviousValue { get { return default(T); } }
|
||||
public T CurrentValue { get { return default(T); } }
|
||||
|
||||
}
|
||||
|
||||
internal sealed class AsyncLocal<T>
|
||||
{
|
||||
public AsyncLocal()
|
||||
{
|
||||
}
|
||||
|
||||
public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
object obj = null; //
|
||||
return (obj == null) ? default(T) : (T)obj;
|
||||
}
|
||||
set
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace System.Diagnostics.Tracing
|
||||
private static WriteEventErrorCode s_returnCode; // The last return code
|
||||
|
||||
private const int s_basicTypeAllocationBufferSize = 16;
|
||||
private const int s_etwMaxNumberArguments = 32;
|
||||
private const int s_etwMaxNumberArguments = 128;
|
||||
private const int s_etwAPIMaxRefObjCount = 8;
|
||||
private const int s_maxEventDataDescriptors = 128;
|
||||
private const int s_traceEventMaximumSize = 65482;
|
||||
|
||||
@@ -1 +1 @@
|
||||
a1b51851218d5fc20ec8ab7c6933e742e0f6a94b
|
||||
9ae566937256255d1b55dcc7c0b259983dc54595
|
||||
@@ -416,7 +416,7 @@ namespace System {
|
||||
|
||||
#if !FEATURE_CORECLR
|
||||
// Do security check
|
||||
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
|
||||
FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, path);
|
||||
#endif
|
||||
|
||||
return path;
|
||||
|
||||
@@ -429,7 +429,7 @@ namespace System {
|
||||
|
||||
#if MONO
|
||||
if (method != null) { // source can be null
|
||||
_source = method.DeclaringType.Assembly.UnprotectedGetName ().Name;
|
||||
_source = method.DeclaringType.Assembly.GetName ().Name;
|
||||
}
|
||||
#else
|
||||
Module module = method.Module;
|
||||
|
||||
@@ -65,6 +65,28 @@ namespace System {
|
||||
|
||||
public static class GC
|
||||
{
|
||||
#if MONO
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
extern static int GetCollectionCount (int generation);
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
extern static int GetMaxGeneration ();
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
extern static void InternalCollect (int generation);
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
extern static void RecordPressure (long bytesAllocated);
|
||||
|
||||
// TODO: Move following to ConditionalWeakTable
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
internal extern static void register_ephemeron_array (Ephemeron[] array);
|
||||
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
extern static object get_ephemeron_tombstone ();
|
||||
|
||||
internal static readonly object EPHEMERON_TOMBSTONE = get_ephemeron_tombstone ();
|
||||
#else
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
@@ -139,6 +161,7 @@ namespace System {
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
|
||||
private static extern void _RemoveMemoryPressure(UInt64 bytesAllocated);
|
||||
#endif
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated_required
|
||||
public static void AddMemoryPressure (long bytesAllocated) {
|
||||
@@ -153,7 +176,11 @@ namespace System {
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
#if MONO
|
||||
RecordPressure (bytesAllocated);
|
||||
#else
|
||||
_AddMemoryPressure((ulong)bytesAllocated);
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Security.SecurityCritical] // auto-generated_required
|
||||
@@ -169,7 +196,11 @@ namespace System {
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
#if MONO
|
||||
RecordPressure (-bytesAllocated);
|
||||
#else
|
||||
_RemoveMemoryPressure((ulong) bytesAllocated);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -198,8 +229,12 @@ namespace System {
|
||||
//
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public static void Collect() {
|
||||
#if MONO
|
||||
InternalCollect (MaxGeneration);
|
||||
#else
|
||||
//-1 says to GC all generations.
|
||||
_Collect(-1, (int)InternalGCCollectionMode.Blocking);
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
@@ -248,7 +283,11 @@ namespace System {
|
||||
iInternalModes |= (int)InternalGCCollectionMode.NonBlocking;
|
||||
}
|
||||
|
||||
#if MONO
|
||||
InternalCollect (generation);
|
||||
#else
|
||||
_Collect(generation, iInternalModes);
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
@@ -260,9 +299,15 @@ namespace System {
|
||||
throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
|
||||
}
|
||||
Contract.EndContractBlock();
|
||||
|
||||
#if MONO
|
||||
return GetCollectionCount(generation);
|
||||
#else
|
||||
return _CollectionCount(generation, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !MONO
|
||||
// pass in true to get the BGC or FGC count.
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
@@ -275,6 +320,7 @@ namespace System {
|
||||
Contract.EndContractBlock();
|
||||
return _CollectionCount(generation, (getSpecialGCCount ? 1 : 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
// This method DOES NOT DO ANYTHING in and of itself. It's used to
|
||||
// prevent a finalizable object from losing any outstanding references
|
||||
@@ -318,9 +364,16 @@ namespace System {
|
||||
//
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public static int GetGeneration(WeakReference wo) {
|
||||
#if MONO
|
||||
object obj = wo.Target;
|
||||
if (obj == null)
|
||||
throw new ArgumentException ();
|
||||
return GetGeneration (obj);
|
||||
#else
|
||||
int result = GetGenerationWR(wo.m_handle);
|
||||
KeepAlive(wo);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the maximum GC generation. Currently assumes only 1 heap.
|
||||
@@ -330,17 +383,23 @@ namespace System {
|
||||
get { return GetMaxGeneration(); }
|
||||
}
|
||||
|
||||
#if MONO
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
public extern static void WaitForPendingFinalizers ();
|
||||
#else
|
||||
[System.Security.SecurityCritical] // auto-generated
|
||||
[ResourceExposure(ResourceScope.None)]
|
||||
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
private static extern void _WaitForPendingFinalizers();
|
||||
|
||||
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public static void WaitForPendingFinalizers() {
|
||||
// QCalls can not be exposed from mscorlib directly, need to wrap it.
|
||||
_WaitForPendingFinalizers();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Indicates that the system should not call the Finalize() method on
|
||||
// an object that would normally require this call.
|
||||
@@ -380,6 +439,31 @@ namespace System {
|
||||
// the GC heap. This does not return the total size of the GC heap, but
|
||||
// only the live objects in the GC heap.
|
||||
//
|
||||
#if MONO
|
||||
[MethodImplAttribute (MethodImplOptions.InternalCall)]
|
||||
public extern static long GetTotalMemory (bool forceFullCollection);
|
||||
|
||||
static bool _RegisterForFullGCNotification(int maxGenerationPercentage, int largeObjectHeapPercentage)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
static bool _CancelFullGCNotification ()
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
static int _WaitForFullGCApproach (int millisecondsTimeout)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
static int _WaitForFullGCComplete (int millisecondsTimeout)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
#else
|
||||
[System.Security.SecuritySafeCritical] // auto-generated
|
||||
public static long GetTotalMemory(bool forceFullCollection) {
|
||||
long size = GetTotalMemory();
|
||||
@@ -416,6 +500,7 @@ namespace System {
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
private static extern int _WaitForFullGCComplete(int millisecondsTimeout);
|
||||
#endif
|
||||
|
||||
[SecurityCritical]
|
||||
public static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold)
|
||||
@@ -503,6 +588,9 @@ namespace System {
|
||||
[SecurityCritical]
|
||||
static bool StartNoGCRegionWorker(long totalSize, bool hasLohSize, long lohSize, bool disallowFullBlockingGC)
|
||||
{
|
||||
#if MONO
|
||||
throw new NotImplementedException ();
|
||||
#else
|
||||
StartNoGCRegionStatus status = (StartNoGCRegionStatus)_StartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC);
|
||||
if (status == StartNoGCRegionStatus.AmountTooLarge)
|
||||
throw new ArgumentOutOfRangeException("totalSize",
|
||||
@@ -512,6 +600,7 @@ namespace System {
|
||||
else if (status == StartNoGCRegionStatus.NotEnoughMemory)
|
||||
return false;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
@@ -541,6 +630,9 @@ namespace System {
|
||||
[SecurityCritical]
|
||||
static EndNoGCRegionStatus EndNoGCRegionWorker()
|
||||
{
|
||||
#if MONO
|
||||
throw new NotImplementedException ();
|
||||
#else
|
||||
EndNoGCRegionStatus status = (EndNoGCRegionStatus)_EndNoGCRegion();
|
||||
if (status == EndNoGCRegionStatus.NotInProgress)
|
||||
throw new InvalidOperationException("NoGCRegion mode must be set");
|
||||
@@ -550,6 +642,7 @@ namespace System {
|
||||
throw new InvalidOperationException("Allocated memory exceeds specified memory for NoGCRegion mode");
|
||||
|
||||
return EndNoGCRegionStatus.Succeeded;
|
||||
#endif
|
||||
}
|
||||
|
||||
[SecurityCritical]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user