Avoid multiple initializations of AmdGpu (#1324)

ADL finds multiple logical gpus, this commit avoids multiple
unneeded initializations of AmdGpu class. The main control is moved to
AmdGpuGroup and the ADL_* calls are updated to ADL2_*, using the
context. Adapters using PMlog should be initialized only if sensors are
detected, adapters that pmlog is not enabled or doesn't work, should
fallback previous logic.
This commit is contained in:
Emerson Pinter
2024-05-02 21:42:22 +02:00
committed by GitHub
parent 0c3ebb1933
commit 07234e3594
3 changed files with 96 additions and 75 deletions
+8 -21
View File
@@ -58,9 +58,11 @@ internal sealed class AmdGpu : GenericGpu
private readonly ushort _pmLogSampleRate = 1000; private readonly ushort _pmLogSampleRate = 1000;
private bool _overdrive8LogExists; private bool _overdrive8LogExists;
public AmdGpu(AtiAdlxx.ADLAdapterInfo adapterInfo, ISettings settings) public AmdGpu(IntPtr amdContext, AtiAdlxx.ADLAdapterInfo adapterInfo, AtiAdlxx.ADLGcnInfo gcnInfo, ISettings settings)
: base(adapterInfo.AdapterName.Trim(), new Identifier("gpu-amd", adapterInfo.AdapterIndex.ToString(CultureInfo.InvariantCulture)), settings) : base(adapterInfo.AdapterName.Trim(), new Identifier("gpu-amd", adapterInfo.AdapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
{ {
_context = amdContext;
_adlGcnInfo = gcnInfo;
_adapterInfo = adapterInfo; _adapterInfo = adapterInfo;
BusNumber = adapterInfo.BusNumber; BusNumber = adapterInfo.BusNumber;
DeviceNumber = adapterInfo.DeviceNumber; DeviceNumber = adapterInfo.DeviceNumber;
@@ -137,13 +139,6 @@ internal sealed class AmdGpu : GenericGpu
int supported = 0; int supported = 0;
int enabled = 0; int enabled = 0;
int version = 0; int version = 0;
_adlGcnInfo = new();
if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Main_Control_Create)) &&
AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, _adapterInfo.AdapterIndex, ref _context) != AtiAdlxx.ADLStatus.ADL_OK)
{
_context = IntPtr.Zero;
}
if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_FrameMetrics_Caps)) && if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_FrameMetrics_Caps)) &&
AtiAdlxx.ADL2_Adapter_FrameMetrics_Caps(_context, _adapterInfo.AdapterIndex, ref supported) == AtiAdlxx.ADLStatus.ADL_OK && AtiAdlxx.ADL2_Adapter_FrameMetrics_Caps(_context, _adapterInfo.AdapterIndex, ref supported) == AtiAdlxx.ADLStatus.ADL_OK &&
@@ -155,12 +150,7 @@ internal sealed class AmdGpu : GenericGpu
ActivateSensor(_fullscreenFps); ActivateSensor(_fullscreenFps);
} }
if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_GcnAsicInfo_Get))) if (AtiAdlxx.UsePmLogForFamily(_adlGcnInfo.ASICFamilyId) &&
{
AtiAdlxx.ADL2_GcnAsicInfo_Get(_context, _adapterInfo.AdapterIndex, ref _adlGcnInfo);
}
if (_adlGcnInfo.ASICFamilyId >= (int)AtiAdlxx.GCNFamilies.FAMILY_AI &&
AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Support_Get)) && AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Support_Get)) &&
AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Device_PMLog_Device_Create)) && AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Device_PMLog_Device_Create)) &&
AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Start))) AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Start)))
@@ -169,7 +159,7 @@ internal sealed class AmdGpu : GenericGpu
_adlPMLogSupportInfo = new(); _adlPMLogSupportInfo = new();
_adlPMLogStartOutput = new AtiAdlxx.ADLPMLogStartOutput(); _adlPMLogStartOutput = new AtiAdlxx.ADLPMLogStartOutput();
_adlPMLogStartInput.usSensors = new ushort[AtiAdlxx.ADL_PMLOG_MAX_SENSORS]; _adlPMLogStartInput.usSensors = new ushort[AtiAdlxx.ADL_PMLOG_MAX_SENSORS];
if (_device == 0 && if (_device == 0 &&
AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Device_PMLog_Device_Create(_context, _adapterInfo.AdapterIndex, ref _device) && AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Device_PMLog_Device_Create(_context, _adapterInfo.AdapterIndex, ref _device) &&
AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Adapter_PMLog_Support_Get(_context, _adapterInfo.AdapterIndex, ref _adlPMLogSupportInfo)) AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Adapter_PMLog_Support_Get(_context, _adapterInfo.AdapterIndex, ref _adlPMLogSupportInfo))
@@ -406,7 +396,7 @@ internal sealed class AmdGpu : GenericGpu
private bool IsSensorSupportedByPMLog(AtiAdlxx.ADLPMLogSensors sensorType) private bool IsSensorSupportedByPMLog(AtiAdlxx.ADLPMLogSensors sensorType)
{ {
if (!_pmLogStarted || (int)sensorType == 0) if (!_pmLogStarted || (int)sensorType == 0)
return false; return false;
for (int i = 0; i < AtiAdlxx.ADL_PMLOG_MAX_SENSORS; i++) for (int i = 0; i < AtiAdlxx.ADL_PMLOG_MAX_SENSORS; i++)
@@ -440,7 +430,7 @@ internal sealed class AmdGpu : GenericGpu
if (!supportedByPMLog && !supportedByOD8) if (!supportedByPMLog && !supportedByOD8)
{ {
if (reset) if (reset)
sensor.Value = null; sensor.Value = null;
return false; return false;
@@ -642,9 +632,6 @@ internal sealed class AmdGpu : GenericGpu
AtiAdlxx.ADL2_Device_PMLog_Device_Destroy(_context, _device); AtiAdlxx.ADL2_Device_PMLog_Device_Destroy(_context, _device);
} }
if (_context != IntPtr.Zero)
AtiAdlxx.ADL2_Main_Control_Destroy(_context);
base.Close(); base.Close();
} }
@@ -893,7 +880,7 @@ internal sealed class AmdGpu : GenericGpu
foreach (AtiAdlxx.ADLPMLogSensors sensorType in Enum.GetValues(typeof(AtiAdlxx.ADLPMLogSensors))) foreach (AtiAdlxx.ADLPMLogSensors sensorType in Enum.GetValues(typeof(AtiAdlxx.ADLPMLogSensors)))
{ {
int i = (int)sensorType; int i = (int)sensorType;
if (i == 0) if (i == 0)
continue; continue;
bool supported = false; bool supported = false;
@@ -15,6 +15,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu;
internal class AmdGpuGroup : IGroup internal class AmdGpuGroup : IGroup
{ {
private readonly IntPtr _context = IntPtr.Zero;
private readonly List<AmdGpu> _hardware = new(); private readonly List<AmdGpu> _hardware = new();
private readonly StringBuilder _report = new(); private readonly StringBuilder _report = new();
private readonly AtiAdlxx.ADLStatus _status; private readonly AtiAdlxx.ADLStatus _status;
@@ -23,7 +24,7 @@ internal class AmdGpuGroup : IGroup
{ {
try try
{ {
_status = AtiAdlxx.ADL_Main_Control_Create(1); _status = AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, 1, ref _context);
_report.AppendLine("AMD Display Library"); _report.AppendLine("AMD Display Library");
_report.AppendLine(); _report.AppendLine();
@@ -34,7 +35,7 @@ internal class AmdGpuGroup : IGroup
if (_status == AtiAdlxx.ADLStatus.ADL_OK) if (_status == AtiAdlxx.ADLStatus.ADL_OK)
{ {
int numberOfAdapters = 0; int numberOfAdapters = 0;
AtiAdlxx.ADL_Adapter_NumberOfAdapters_Get(ref numberOfAdapters); AtiAdlxx.ADL2_Adapter_NumberOfAdapters_Get(_context, ref numberOfAdapters);
_report.Append("Number of adapters: "); _report.Append("Number of adapters: ");
_report.AppendLine(numberOfAdapters.ToString(CultureInfo.InvariantCulture)); _report.AppendLine(numberOfAdapters.ToString(CultureInfo.InvariantCulture));
@@ -45,15 +46,23 @@ internal class AmdGpuGroup : IGroup
List<AmdGpu> potentialHardware = new(); List<AmdGpu> potentialHardware = new();
AtiAdlxx.ADLAdapterInfo[] adapterInfo = new AtiAdlxx.ADLAdapterInfo[numberOfAdapters]; AtiAdlxx.ADLAdapterInfo[] adapterInfo = new AtiAdlxx.ADLAdapterInfo[numberOfAdapters];
if (AtiAdlxx.ADL_Adapter_AdapterInfo_Get(adapterInfo) == AtiAdlxx.ADLStatus.ADL_OK) if (AtiAdlxx.ADL2_Adapter_AdapterInfo_Get(ref _context, adapterInfo) == AtiAdlxx.ADLStatus.ADL_OK)
{ {
for (int i = 0; i < numberOfAdapters; i++) for (int i = 0; i < numberOfAdapters; i++)
{ {
AtiAdlxx.ADL_Adapter_Active_Get(adapterInfo[i].AdapterIndex, out int isActive); uint device = 0;
AtiAdlxx.ADLGcnInfo gcnInfo = new();
AtiAdlxx.ADLPMLogSupportInfo pmLogSupportInfo = new();
AtiAdlxx.ADL2_Adapter_Active_Get(_context, adapterInfo[i].AdapterIndex, out int isActive);
if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_GcnAsicInfo_Get)))
{
AtiAdlxx.ADL2_GcnAsicInfo_Get(_context, adapterInfo[i].AdapterIndex, ref gcnInfo);
}
int adapterId = -1; int adapterId = -1;
if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL_Adapter_ID_Get))) if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_ID_Get)))
AtiAdlxx.ADL_Adapter_ID_Get(adapterInfo[i].AdapterIndex, out adapterId); AtiAdlxx.ADL2_Adapter_ID_Get(_context, adapterInfo[i].AdapterIndex, out adapterId);
_report.Append("AdapterIndex: "); _report.Append("AdapterIndex: ");
_report.AppendLine(i.ToString(CultureInfo.InvariantCulture)); _report.AppendLine(i.ToString(CultureInfo.InvariantCulture));
@@ -77,9 +86,43 @@ internal class AmdGpuGroup : IGroup
_report.AppendLine(adapterInfo[i].FunctionNumber.ToString(CultureInfo.InvariantCulture)); _report.AppendLine(adapterInfo[i].FunctionNumber.ToString(CultureInfo.InvariantCulture));
_report.Append("AdapterID: 0x"); _report.Append("AdapterID: 0x");
_report.AppendLine(adapterId.ToString("X", CultureInfo.InvariantCulture)); _report.AppendLine(adapterId.ToString("X", CultureInfo.InvariantCulture));
_report.AppendLine("Family: " + gcnInfo.ASICFamilyId);
if (!string.IsNullOrEmpty(adapterInfo[i].UDID) && adapterInfo[i].VendorID == AtiAdlxx.ATI_VENDOR_ID) int sensorsSupported = 0;
potentialHardware.Add(new AmdGpu(adapterInfo[i], settings)); if (AtiAdlxx.UsePmLogForFamily(gcnInfo.ASICFamilyId) &&
AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Support_Get)) &&
AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Device_PMLog_Device_Create)))
{
if (AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Device_PMLog_Device_Create(_context, adapterInfo[i].AdapterIndex, ref device) &&
AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Adapter_PMLog_Support_Get(_context, adapterInfo[i].AdapterIndex, ref pmLogSupportInfo))
{
int k = 0;
while (pmLogSupportInfo.usSensors[k] != (ushort)AtiAdlxx.ADLPMLogSensors.ADL_SENSOR_MAXTYPES)
{
k++;
}
sensorsSupported = k;
}
_report.AppendLine("Sensors Supported: " + sensorsSupported);
if (device != 0)
{
AtiAdlxx.ADL2_Device_PMLog_Device_Destroy(_context, device);
}
}
if (!string.IsNullOrEmpty(adapterInfo[i].UDID) && adapterInfo[i].VendorID == AtiAdlxx.ATI_VENDOR_ID &&
!IsAlreadyAdded(adapterInfo[i].BusNumber, adapterInfo[i].DeviceNumber))
{
if (sensorsSupported > 0)
{
_hardware.Add(new AmdGpu(_context, adapterInfo[i], gcnInfo, settings));
}
else
{
potentialHardware.Add(new AmdGpu(_context, adapterInfo[i], gcnInfo, settings));
}
}
_report.AppendLine(); _report.AppendLine();
} }
@@ -88,7 +131,7 @@ internal class AmdGpuGroup : IGroup
foreach (IGrouping<string, AmdGpu> amdGpus in potentialHardware.GroupBy(x => $"{x.BusNumber}-{x.DeviceNumber}")) foreach (IGrouping<string, AmdGpu> amdGpus in potentialHardware.GroupBy(x => $"{x.BusNumber}-{x.DeviceNumber}"))
{ {
AmdGpu amdGpu = amdGpus.OrderByDescending(x => x.Sensors.Length).FirstOrDefault(); AmdGpu amdGpu = amdGpus.OrderByDescending(x => x.Sensors.Length).FirstOrDefault();
if (amdGpu != null) if (amdGpu != null && !IsAlreadyAdded(amdGpu.BusNumber, amdGpu.DeviceNumber))
_hardware.Add(amdGpu); _hardware.Add(amdGpu);
} }
} }
@@ -104,6 +147,18 @@ internal class AmdGpuGroup : IGroup
} }
} }
private bool IsAlreadyAdded(int busNumber, int deviceNumber)
{
foreach (AmdGpu g in _hardware)
{
if (g.BusNumber == busNumber && g.DeviceNumber == deviceNumber)
{
return true;
}
}
return false;
}
public IReadOnlyList<IHardware> Hardware => _hardware; public IReadOnlyList<IHardware> Hardware => _hardware;
public string GetReport() public string GetReport()
@@ -118,8 +173,8 @@ internal class AmdGpuGroup : IGroup
foreach (AmdGpu gpu in _hardware) foreach (AmdGpu gpu in _hardware)
gpu.Close(); gpu.Close();
if (_status == AtiAdlxx.ADLStatus.ADL_OK) if (_status == AtiAdlxx.ADLStatus.ADL_OK && _context != IntPtr.Zero)
AtiAdlxx.ADL_Main_Control_Destroy(); AtiAdlxx.ADL2_Main_Control_Destroy(_context);
} }
catch (Exception) catch (Exception)
{ } { }
+22 -43
View File
@@ -50,38 +50,6 @@ internal static class AtiAdlxx
public delegate IntPtr Context(int size); public delegate IntPtr Context(int size);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Main_Control_Create(ADL_Main_Memory_AllocDelegate callback, int enumConnectedAdapters);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Main_Control_Destroy();
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Adapter_AdapterInfo_Get(IntPtr info, int size);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Adapter_NumberOfAdapters_Get();
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Adapter_NumberOfAdapters_Get(ref int numAdapters);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Adapter_ID_Get(int adapterIndex, out int adapterId);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Display_AdapterID_Get(int adapterIndex, out int adapterId);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Adapter_Active_Get(int adapterIndex, out int status);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Overdrive5_ODParameters_Get(int adapterIndex, out ADLODParameters parameters); public static extern ADLStatus ADL_Overdrive5_ODParameters_Get(int adapterIndex, out ADLODParameters parameters);
@@ -142,10 +110,6 @@ internal static class AtiAdlxx
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL2_New_QueryPMLogData_Get(IntPtr context, int adapterIndex, ref ADLPMLogDataOutput aDLPMLogDataOutput); public static extern ADLStatus ADL2_New_QueryPMLogData_Get(IntPtr context, int adapterIndex, ref ADLPMLogDataOutput aDLPMLogDataOutput);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL_Graphics_Versions_Get(out ADLVersionsInfo versionInfo);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL2_Adapter_FrameMetrics_Caps(IntPtr context, int adapterIndex, ref int supported); public static extern ADLStatus ADL2_Adapter_FrameMetrics_Caps(IntPtr context, int adapterIndex, ref int supported);
@@ -190,6 +154,22 @@ internal static class AtiAdlxx
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL2_GcnAsicInfo_Get(IntPtr context, int adapterIndex, ref ADLGcnInfo gcnInfo); public static extern ADLStatus ADL2_GcnAsicInfo_Get(IntPtr context, int adapterIndex, ref ADLGcnInfo gcnInfo);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL2_Adapter_NumberOfAdapters_Get(IntPtr context, ref int numAdapters);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL2_Adapter_AdapterInfo_Get(IntPtr context, IntPtr adapterInfo, int size);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL2_Adapter_ID_Get(IntPtr context, int adapterIndex, out int adapterId);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
public static extern ADLStatus ADL2_Adapter_Active_Get(IntPtr context, int adapterIndex, out int status);
public static bool ADL_Method_Exists(string ADL_Method) public static bool ADL_Method_Exists(string ADL_Method)
{ {
IntPtr module = Kernel32.LoadLibrary(DllName); IntPtr module = Kernel32.LoadLibrary(DllName);
@@ -203,11 +183,11 @@ internal static class AtiAdlxx
return false; return false;
} }
public static ADLStatus ADL_Main_Control_Create(int enumConnectedAdapters) public static ADLStatus ADL2_Main_Control_Create(IntPtr context, int enumConnectedAdapters)
{ {
try try
{ {
return ADL_Method_Exists(nameof(ADL_Main_Control_Create)) ? ADL_Main_Control_Create(Main_Memory_Alloc, enumConnectedAdapters) : ADLStatus.ADL_ERR; return ADL_Method_Exists(nameof(ADL2_Main_Control_Create)) ? ADL2_Main_Control_Create(Main_Memory_Alloc, enumConnectedAdapters, ref context) : ADLStatus.ADL_ERR;
} }
catch catch
{ {
@@ -215,12 +195,12 @@ internal static class AtiAdlxx
} }
} }
public static ADLStatus ADL_Adapter_AdapterInfo_Get(ADLAdapterInfo[] info) public static ADLStatus ADL2_Adapter_AdapterInfo_Get(ref IntPtr context, ADLAdapterInfo[] info)
{ {
int elementSize = Marshal.SizeOf(typeof(ADLAdapterInfo)); int elementSize = Marshal.SizeOf(typeof(ADLAdapterInfo));
int size = info.Length * elementSize; int size = info.Length * elementSize;
IntPtr ptr = Marshal.AllocHGlobal(size); IntPtr ptr = Marshal.AllocHGlobal(size);
ADLStatus result = ADL_Adapter_AdapterInfo_Get(ptr, size); ADLStatus result = ADL2_Adapter_AdapterInfo_Get(context, ptr, size);
for (int i = 0; i < info.Length; i++) for (int i = 0; i < info.Length; i++)
info[i] = (ADLAdapterInfo)Marshal.PtrToStructure((IntPtr)((long)ptr + (i * elementSize)), typeof(ADLAdapterInfo)); info[i] = (ADLAdapterInfo)Marshal.PtrToStructure((IntPtr)((long)ptr + (i * elementSize)), typeof(ADLAdapterInfo));
@@ -249,10 +229,9 @@ internal static class AtiAdlxx
return result; return result;
} }
public static void Main_Memory_Free(IntPtr buffer) public static bool UsePmLogForFamily(int familyId)
{ {
if (IntPtr.Zero != buffer) return familyId >= (int)GCNFamilies.FAMILY_AI;
Marshal.FreeHGlobal(buffer);
} }
internal enum ADLStatus internal enum ADLStatus