80 lines
3.2 KiB
C#
80 lines
3.2 KiB
C#
|
//----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------------------
|
||
|
namespace System.ServiceModel.Activation
|
||
|
{
|
||
|
using System.ComponentModel;
|
||
|
using System.Runtime;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Security;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.Threading;
|
||
|
|
||
|
static class ServiceMemoryGates
|
||
|
{
|
||
|
[Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical helper methods to check memory status." +
|
||
|
"Allocates unmanaged resources, can only be called with admin-specified value.")]
|
||
|
[SecurityCritical]
|
||
|
internal static bool Check(int minFreeMemoryPercentage, bool throwOnLowMemory, out ulong availableMemoryBytes)
|
||
|
{
|
||
|
// Boundary check percentage, if out of bounds Gate is turned off.
|
||
|
// 0 is defined as disabled. Configuration defines 99 as max allowed so we disable
|
||
|
// if we receive something out of range
|
||
|
availableMemoryBytes = 0;
|
||
|
if (minFreeMemoryPercentage < 1 || minFreeMemoryPercentage > 99)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
UnsafeNativeMethods.MEMORYSTATUSEX memoryStatus = new UnsafeNativeMethods.MEMORYSTATUSEX();
|
||
|
GetGlobalMemoryStatus(ref memoryStatus);
|
||
|
|
||
|
if (memoryStatus.ullAvailVirtual < (memoryStatus.ullTotalVirtual / 100 * (ulong)minFreeMemoryPercentage))
|
||
|
{
|
||
|
availableMemoryBytes = memoryStatus.ullAvailVirtual;
|
||
|
}
|
||
|
else if (memoryStatus.ullAvailPhys < (memoryStatus.ullTotalPhys / 100 * (ulong)minFreeMemoryPercentage))
|
||
|
{
|
||
|
availableMemoryBytes = memoryStatus.ullAvailPhys;
|
||
|
}
|
||
|
|
||
|
if (TD.ServiceActivationAvailableMemoryIsEnabled())
|
||
|
{
|
||
|
TD.ServiceActivationAvailableMemory(availableMemoryBytes);
|
||
|
}
|
||
|
|
||
|
if (availableMemoryBytes != 0)
|
||
|
{
|
||
|
if (throwOnLowMemory)
|
||
|
{
|
||
|
throw FxTrace.Exception.AsError(new InsufficientMemoryException(
|
||
|
SR.Hosting_MemoryGatesCheckFailed(availableMemoryBytes,
|
||
|
minFreeMemoryPercentage)));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
[Fx.Tag.SecurityNote(Critical = "Uses UnsafeNativeMethods to fetch memory status structure, caller must not leak it.")]
|
||
|
[SecurityCritical]
|
||
|
static void GetGlobalMemoryStatus(ref UnsafeNativeMethods.MEMORYSTATUSEX memoryStatus)
|
||
|
{
|
||
|
memoryStatus.dwLength = (uint)Marshal.SizeOf(typeof(UnsafeNativeMethods.MEMORYSTATUSEX));
|
||
|
|
||
|
if (!UnsafeNativeMethods.GlobalMemoryStatusEx(ref memoryStatus))
|
||
|
{
|
||
|
int error = Marshal.GetLastWin32Error();
|
||
|
// Treat as the worst case.
|
||
|
throw FxTrace.Exception.AsError(
|
||
|
new InvalidOperationException(SR.Hosting_GetGlobalMemoryFailed, new Win32Exception(error)));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|