This code loops through the result for a call to GetLogicalProcessorInformation and counts the number of processors and cores.
Signed-off-by: Darryl L. Pierce dpierce@redhat.com --- src/host.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 95 insertions(+), 1 deletions(-)
diff --git a/src/host.cpp b/src/host.cpp index d6955a5..c9135d5 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -36,6 +36,56 @@ extern "C" {
using namespace std;
+#ifdef WIN32 + +/* The following definitions make up for what is lacking currently + * in the MinGW packages, and should be moved out to them at some + * point in future. + */ + +typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { + RelationProcessorCore, + RelationNumaNode, + RelationCache, + RelationProcessorPackage, + RelationGroup, + RelationAll = 0xffff +} LOGICAL_PROCESSOR_RELATIONSHIP; + +typedef enum _PROCESSOR_CACHE_TYPE { + CacheUnified, + CacheInstruction, + CacheData, + CacheTrace +} PROCESSOR_CACHE_TYPE; + +typedef struct _CACHE_DESCRIPTOR { + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD Size; + PROCESSOR_CACHE_TYPE Type; +} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR; + +typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { + ULONG_PTR ProcessorMask; + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + union { + struct { + BYTE Flags; + } ProcessorCore; + struct { + DWORD NodeNumber; + } NumaNode; + CACHE_DESCRIPTOR Cache; + ULONGLONG Reserved[2]; + } ; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; + +typedef BOOL (WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD); + +#endif + typedef struct cpuinfo_ { static bool initialized; @@ -260,8 +310,52 @@ host_get_cpu_details() input.close(); cpuinfo.cpus /= cpuinfo.cores; } -#endif +#elif defined WIN32 + LPFN_GLPI proc; + DWORD ret_length; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer, ptr; + + proc = (LPFN_GLPI) GetProcAddress(GetModuleHandle(TEXT("kernel32")), + "GetLogicalProcessorInformation"); + if(proc) + { + BOOL done = FALSE; + + while (!done) + { + DWORD rc = proc(buffer, &ret_length); + + if(rc == FALSE) + { + if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + if(buffer) free(buffer); + + buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(ret_length); + } + } + else + { + done = TRUE; + } + } + + ptr = buffer; + + DWORD offset = 0;
+ while(offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= ret_length) + { + switch(ptr->Relationship) + { + case RelationProcessorCore: cpuinfo.cores++; break; + case RelationProcessorPackage: cpuinfo.cpus++; break; + } + } + + if(buffer) free(buffer); + } +#endif }
string
No objections.
One minor thing, the if-clause is redundant for the calls to free(). Presumably ret_length contains the length required not the length returned?
On Tue, Jul 27, 2010 at 10:17 PM, Darryl L. Pierce dpierce@redhat.com wrote:
This code loops through the result for a call to GetLogicalProcessorInformation and counts the number of processors and cores.
Signed-off-by: Darryl L. Pierce dpierce@redhat.com
src/host.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 95 insertions(+), 1 deletions(-)
diff --git a/src/host.cpp b/src/host.cpp index d6955a5..c9135d5 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -36,6 +36,56 @@ extern "C" {
using namespace std;
+#ifdef WIN32
+/* The following definitions make up for what is lacking currently
- in the MinGW packages, and should be moved out to them at some
- point in future.
- */
+typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
- RelationProcessorCore,
- RelationNumaNode,
- RelationCache,
- RelationProcessorPackage,
- RelationGroup,
- RelationAll = 0xffff
+} LOGICAL_PROCESSOR_RELATIONSHIP;
+typedef enum _PROCESSOR_CACHE_TYPE {
- CacheUnified,
- CacheInstruction,
- CacheData,
- CacheTrace
+} PROCESSOR_CACHE_TYPE;
+typedef struct _CACHE_DESCRIPTOR {
- BYTE Level;
- BYTE Associativity;
- WORD LineSize;
- DWORD Size;
- PROCESSOR_CACHE_TYPE Type;
+} CACHE_DESCRIPTOR, *PCACHE_DESCRIPTOR;
+typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
- ULONG_PTR ProcessorMask;
- LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
- union {
- struct {
- BYTE Flags;
- } ProcessorCore;
- struct {
- DWORD NodeNumber;
- } NumaNode;
- CACHE_DESCRIPTOR Cache;
- ULONGLONG Reserved[2];
- } ;
+} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
+typedef BOOL (WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+#endif
typedef struct cpuinfo_ { static bool initialized; @@ -260,8 +310,52 @@ host_get_cpu_details() input.close(); cpuinfo.cpus /= cpuinfo.cores; } -#endif +#elif defined WIN32
LPFN_GLPI proc;
DWORD ret_length;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer, ptr;
proc = (LPFN_GLPI) GetProcAddress(GetModuleHandle(TEXT("kernel32")),
"GetLogicalProcessorInformation");
if(proc)
{
BOOL done = FALSE;
while (!done)
{
DWORD rc = proc(buffer, &ret_length);
if(rc == FALSE)
{
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
if(buffer) free(buffer);
buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(ret_length);
}
}
else
{
done = TRUE;
}
}
ptr = buffer;
DWORD offset = 0;
while(offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= ret_length)
{
switch(ptr->Relationship)
{
case RelationProcessorCore: cpuinfo.cores++; break;
case RelationProcessorPackage: cpuinfo.cpus++; break;
}
}
if(buffer) free(buffer);
}
+#endif }
string
1.7.2
Matahari mailing list Matahari@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/matahari
On Fri, Jul 30, 2010 at 02:06:02PM +0200, Andrew Beekhof wrote:
No objections.
One minor thing, the if-clause is redundant for the calls to free().
I don't think so. The first one does a free() on the original buffer allocated if the buffer was too small for the API. The second call releases memory being held by the buffer regardless of which path it took. Though, in thinking about it, the call ought to be replaced with a macro that releases the memory and then sets the pointer to NULL to avoid any future change trying to double-release memory.
Presumably ret_length contains the length required not the length returned?
Correct. It's the way the API returns the length needed if the originally allocated buffer is too small.
I'll push this with a macro for the call to free().
On Fri, Jul 30, 2010 at 3:13 PM, Darryl L. Pierce dpierce@redhat.com wrote:
On Fri, Jul 30, 2010 at 02:06:02PM +0200, Andrew Beekhof wrote:
No objections.
One minor thing, the if-clause is redundant for the calls to free().
I don't think so. The first one does a free() on the original buffer allocated if the buffer was too small for the API. The second call releases memory being held by the buffer regardless of which path it took. Though, in thinking about it, the call ought to be replaced with a macro that releases the memory and then sets the pointer to NULL to avoid any future change trying to double-release memory.
Correct.
The if-clause can't help protect you from multiple free()s. It only becomes relevant if you set the pointer back to NULL, but then it still has no effect because free(NULL) is perfectly legal.
Presumably ret_length contains the length required not the length returned?
Correct. It's the way the API returns the length needed if the originally allocated buffer is too small.
I'll push this with a macro for the call to free().
-- Darryl L. Pierce, Sr. Software Engineer @ Red Hat, Inc. Delivering value year after year. Red Hat ranks #1 in value among software vendors. http://www.redhat.com/promo/vendor/
On Fri, Jul 30, 2010 at 03:55:28PM +0200, Andrew Beekhof wrote:
The if-clause can't help protect you from multiple free()s. It only becomes relevant if you set the pointer back to NULL, but then it still has no effect because free(NULL) is perfectly legal.
Ah! I understand now. No, I didn't realize that free(NULL) was allowed. When did THAT change? :D
matahari@lists.fedorahosted.org