related to: Confusing ReturnLength from Windows GetLogicalProcessorInformationEx function
I have read the documentation for GetLogicalProcessorInformationEx. It states
Buffer [out, optional]
A pointer to a buffer that receives an array of SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX structures. If the function fails, the contents of this buffer are undefined.
Nowhere is the number of elements defined.
I have written a c++ program that uses this and baffled on how to interpret the output. My code makes the assumption that the array size is 1 unless the parameter is
RelationAll
In which case it assumes array size of 4.
Does anyone know the proper way to parse the output of this function?
#include <Windows.h>
#include <memory>
#include <iterator>
#include <ostream>
#include <iostream>
#include <iomanip>
using namespace std;
const int FieldOffsetDecWidth = 5;
const int FieldOffsetHexWidth = 4;
const int FieldWidthDec = 4;
const int LableWidth = 25;
const string TabStr = " ";
const string CacheTypeArray[] =
{
"CacheUnified",
"CacheInstruction",
"CacheData",
"CacheTrace"
};
string ProcessorCacheTypeToString(PROCESSOR_CACHE_TYPE cacheType)
{
if (cacheType >= 0 && cacheType <= _countof(CacheTypeArray))
{
return CacheTypeArray[static_cast<int>(cacheType)];
}
return "unKnown";
}
const string RelationShipArray[] =
{
"RelationProcessorCore",
"RelationNumaNode",
"RelationCache",
"RelationProcessorPackage",
"RelationGroup"
};
string ReleationShipToString(LOGICAL_PROCESSOR_RELATIONSHIP relationship)
{
if (relationship >= 0 && relationship <= _countof(RelationShipArray))
{
return RelationShipArray[static_cast<int>(relationship)];
}
if (relationship == RelationAll)
{
return "RelationAll";
}
return "unKnown";
}
void printFieldOffset(size_t offset)
{
cout << left << dec << setfill(' ') << setw(FieldOffsetDecWidth) << offset
<< right << " (0x" << hex << setfill('0') << setw(FieldOffsetHexWidth) << offset << ")" << dec;
}
void printField(size_t offset, string name, DWORD value)
{
printFieldOffset(offset);
cout << TabStr.c_str() << left << setfill(' ') << setw(LableWidth)
<< name.c_str() << dec << setw(FieldWidthDec) << value << endl;
}
void printRelationship(size_t offset, string name, LOGICAL_PROCESSOR_RELATIONSHIP relationship)
{
printFieldOffset(offset);
cout << TabStr.c_str() << left << setfill(' ') << setw(LableWidth) << name.c_str()
<< ReleationShipToString(relationship).c_str() << endl;
}
void printCacheType(size_t offset, string name, PROCESSOR_CACHE_TYPE cacheType)
{
printFieldOffset(offset);
cout
<< TabStr.c_str() << left << setfill(' ') << setw(LableWidth) << name.c_str()
<< ProcessorCacheTypeToString(cacheType).c_str() << endl;
}
void printFieldHex(size_t offset, string name, size_t value, int width)
{
printFieldOffset(offset);
cout << TabStr.c_str() << left << setfill(' ') << setw(LableWidth) << name.c_str()
<< right << "(0x" << hex << setfill('0') << setw(width) << value << ")" << endl;
}
void printHeader(size_t offset, string name, size_t size)
{
cout << endl;
printFieldOffset(offset);
cout << ' ' << name.c_str() << " [Size " << dec << setfill(' ') << setw(0) << size
<< " (0x" << hex << setfill('0') << setw(FieldOffsetHexWidth) << size << ")]" << endl << dec;
}
void printGROUP_AFFINITY(GROUP_AFFINITY affinity, size_t offset)
{
printHeader(offset, "GROUP_AFFINITY", sizeof GROUP_AFFINITY);
offset += offsetof(GROUP_AFFINITY, Mask);
printFieldHex(offset, "Mask", affinity.Mask, 8);
offset += offsetof(GROUP_AFFINITY, Group);
printField(offset, "Group", affinity.Group);
offset += offsetof(GROUP_AFFINITY, Reserved);
printFieldOffset(offset);
cout << TabStr.c_str() << "Reserved" << endl;\
}
void GetLogicalProcessorInformation(LOGICAL_PROCESSOR_RELATIONSHIP relationship)
{
DWORD returnedLength = 0;
GetLogicalProcessorInformationEx(relationship, nullptr, &returnedLength);
auto buffer = make_unique<byte[]>(returnedLength);
memset(buffer.get(), 0, returnedLength);
auto result = GetLogicalProcessorInformationEx(relationship, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX(buffer.get()), &returnedLength);\
if (!result)
{
cout << "Error GetLogicalProcessorInformationEx" << endl << "Error " << GetLastError() << endl;
return;
}
cout << "GetLogicalProcessorInformationEx for " << ReleationShipToString(relationship).c_str() << endl << "Size = ";
printFieldOffset(returnedLength);
cout << endl;
auto index = 0;
size_t base_offset = 0;
size_t total_size = 0;
auto basePtr = buffer.get();
while (total_size < returnedLength)
{
auto infoPtr = PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX(basePtr);
cout << endl << "==================================================" << endl;
auto offset = base_offset;
printHeader(offset, "SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX", sizeof SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Relationship);
printRelationship(offset, "Relationship", infoPtr->Relationship);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Size);
printField(offset, "Size", infoPtr->Size);
switch (infoPtr->Relationship)
{
case RelationProcessorPackage:
case RelationProcessorCore:
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Processor);
printHeader(offset, "PROCESSOR_RELATIONSHIP", sizeof PROCESSOR_RELATIONSHIP);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Processor.Flags);
printFieldHex(offset, "Flags", infoPtr->Processor.Flags, 2);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Processor.Reserved);
printFieldOffset(offset);
cout << TabStr.c_str() << "Reserved" << endl;
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Processor.GroupCount);
printField(offset, "GroupCount", infoPtr->Processor.GroupCount);
for (auto i = 0; i < infoPtr->Processor.GroupCount; i++)
{
printGROUP_AFFINITY(infoPtr->Processor.GroupMask[i], base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Processor.GroupMask[i]));
}
break;
case RelationNumaNode:
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, NumaNode);
printHeader(offset, "NUMA_NODE_RELATIONSHIP", sizeof NUMA_NODE_RELATIONSHIP);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, NumaNode.NodeNumber);
printField(offset, "NodeNumber", infoPtr->NumaNode.NodeNumber);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, NumaNode.Reserved);
printFieldOffset(offset);
cout << TabStr.c_str() << "Reserved" << endl;
printGROUP_AFFINITY(infoPtr->NumaNode.GroupMask, base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, NumaNode.GroupMask.Mask));
break;
case RelationCache:
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache);
printHeader(offset, "CACHE_RELATIONSHIP", sizeof CACHE_RELATIONSHIP);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.Level);
printField(offset, "Level", infoPtr->Cache.Level);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.Associativity);
printField(offset, "Associativity", infoPtr->Cache.Associativity);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.LineSize);
printField(offset, "LineSize", infoPtr->Cache.LineSize);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.CacheSize);
printFieldHex(offset, "CacheSize", infoPtr->Cache.CacheSize, 4);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.Type);
printCacheType(offset, "Type", infoPtr->Cache.Type);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.Reserved);
printFieldOffset(offset);
cout << TabStr.c_str() << "Reserved" << endl;
printGROUP_AFFINITY(infoPtr->Cache.GroupMask, base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.GroupMask.Mask));
break;
case RelationGroup:
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group);
printHeader(offset, "GROUP_RELATIONSHIP", sizeof CACHE_RELATIONSHIP);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group.MaximumGroupCount);
printField(offset, "MaximumGroupCount", infoPtr->Group.MaximumGroupCount);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group.ActiveGroupCount);
printField(offset, "ActiveGroupCount", infoPtr->Group.ActiveGroupCount);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Cache.Reserved);
printFieldOffset(offset);
cout << TabStr.c_str() << "Reserved" << endl;
for (auto i = 0; i < infoPtr->Group.ActiveGroupCount; i++)
{
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group.GroupInfo[i]);
printHeader(offset, "PROCESSOR_GROUP_INFO", sizeof PROCESSOR_GROUP_INFO);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group.GroupInfo[i].MaximumProcessorCount);
printField(offset, "MaximumProcessorCount", infoPtr->Group.GroupInfo[i].MaximumProcessorCount);
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group.GroupInfo[i].ActiveProcessorCount);
printField(offset, "ActiveProcessorCount", infoPtr->Group.GroupInfo[i].ActiveProcessorCount);
printFieldOffset(offset);
cout << TabStr.c_str() << "Reserved" << endl;
offset = base_offset + offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group.GroupInfo[i].ActiveProcessorMask);
printFieldHex(offset, "ActiveProcessorMask", infoPtr->Group.GroupInfo[i].ActiveProcessorMask, 8);
}
break;
case RelationAll:
break;
default:;
}
total_size += infoPtr->Size;
basePtr += infoPtr->Size;
base_offset += infoPtr->Size;
index++;
}
}
void main(int argc, char* argv[])
{
if (argc != 2)
{
cout
<< "Useage: GetLogicalProcessorInformation relationship" << endl
<< " 0 = RelationProcessorCore" << endl
<< " 1 = RelationNumaNode" << endl
<< " 2 = RelationCache" << endl
<< " 3 = RelationProcessorPackage" << endl
<< " 4 = RelationGroup" << endl
<< "-1 = RelationAll" << endl;
return;
}
auto relationship = LOGICAL_PROCESSOR_RELATIONSHIP(atoi(argv[1]));
if (relationship == LOGICAL_PROCESSOR_RELATIONSHIP(-1))
{
relationship = RelationAll;
}
GetLogicalProcessorInformation(relationship);
}
output
C:\Users\Paul\Perforce\PEB_DEV64\depot\vanguard\RTX\TMManagedProcess\x64\Debug>CoreAndThreadInfoNative.exe 0
GetLogicalProcessorInformationEx for RelationProcessorCore
Size = 384 (0x0180)
==================================================
0 (0x0000) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
0 (0x0000) Relationship RelationProcessorCore
4 (0x0004) Size 48
8 (0x0008) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
8 (0x0008) Flags (0x00)
9 (0x0009) Reserved
30 (0x001e) GroupCount 1
32 (0x0020) GROUP_AFFINITY [Size 16 (0x0010)]
32 (0x0020) Mask (0x00000001)
40 (0x0028) Group 0
50 (0x0032) Reserved
==================================================
48 (0x0030) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
48 (0x0030) Relationship RelationProcessorCore
52 (0x0034) Size 48
56 (0x0038) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
56 (0x0038) Flags (0x00)
57 (0x0039) Reserved
78 (0x004e) GroupCount 1
80 (0x0050) GROUP_AFFINITY [Size 16 (0x0010)]
80 (0x0050) Mask (0x00000002)
88 (0x0058) Group 0
98 (0x0062) Reserved
==================================================
96 (0x0060) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
96 (0x0060) Relationship RelationProcessorCore
100 (0x0064) Size 48
104 (0x0068) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
104 (0x0068) Flags (0x00)
105 (0x0069) Reserved
126 (0x007e) GroupCount 1
128 (0x0080) GROUP_AFFINITY [Size 16 (0x0010)]
128 (0x0080) Mask (0x00000004)
136 (0x0088) Group 0
146 (0x0092) Reserved
==================================================
144 (0x0090) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
144 (0x0090) Relationship RelationProcessorCore
148 (0x0094) Size 48
152 (0x0098) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
152 (0x0098) Flags (0x00)
153 (0x0099) Reserved
174 (0x00ae) GroupCount 1
176 (0x00b0) GROUP_AFFINITY [Size 16 (0x0010)]
176 (0x00b0) Mask (0x00000008)
184 (0x00b8) Group 0
194 (0x00c2) Reserved
==================================================
192 (0x00c0) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
192 (0x00c0) Relationship RelationProcessorCore
196 (0x00c4) Size 48
200 (0x00c8) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
200 (0x00c8) Flags (0x00)
201 (0x00c9) Reserved
222 (0x00de) GroupCount 1
224 (0x00e0) GROUP_AFFINITY [Size 16 (0x0010)]
224 (0x00e0) Mask (0x00000010)
232 (0x00e8) Group 0
242 (0x00f2) Reserved
==================================================
240 (0x00f0) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
240 (0x00f0) Relationship RelationProcessorCore
244 (0x00f4) Size 48
248 (0x00f8) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
248 (0x00f8) Flags (0x00)
249 (0x00f9) Reserved
270 (0x010e) GroupCount 1
272 (0x0110) GROUP_AFFINITY [Size 16 (0x0010)]
272 (0x0110) Mask (0x00000020)
280 (0x0118) Group 0
290 (0x0122) Reserved
==================================================
288 (0x0120) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
288 (0x0120) Relationship RelationProcessorCore
292 (0x0124) Size 48
296 (0x0128) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
296 (0x0128) Flags (0x00)
297 (0x0129) Reserved
318 (0x013e) GroupCount 1
320 (0x0140) GROUP_AFFINITY [Size 16 (0x0010)]
320 (0x0140) Mask (0x00000040)
328 (0x0148) Group 0
338 (0x0152) Reserved
==================================================
336 (0x0150) SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX [Size 80 (0x0050)]
336 (0x0150) Relationship RelationProcessorCore
340 (0x0154) Size 48
344 (0x0158) PROCESSOR_RELATIONSHIP [Size 40 (0x0028)]
344 (0x0158) Flags (0x00)
345 (0x0159) Reserved
366 (0x016e) GroupCount 1
368 (0x0170) GROUP_AFFINITY [Size 16 (0x0010)]
368 (0x0170) Mask (0x00000080)
376 (0x0178) Group 0
386 (0x0182) Reserved
C:\Users\Paul\Perforce\PEB_DEV64\depot\vanguard\RTX\TMManagedProcess\x64\Debug>
Try the following code:
for( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pProcessor = pProcessorInformation->pProcessorEx;
(LPBYTE)pProcessor < ((LPBYTE)pProcessorInformation->pProcessorEx) + pProcessorInformation->dwProcessorExSize;
pProcessor = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)(((LPBYTE)pProcessor) + pProcessor->Size) )
{
// switch on pProcessor->Relationship for RelationProcessorPackage, RelationProcessorCore, etc...
}
pProcessorInformation
is merely a struct
that holds my PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
structure that you get back from calling the API.
User contributions licensed under CC BY-SA 3.0