[PATCH3/3] ntdll: Retrieve Logical Processor Information from SysFS
Rudolf Mayerhofer
rm at eightyfive.net
Fri Oct 1 14:21:54 CDT 2010
Retrieves Logical Processor Information from SysFS on Linux and
stores them while SYSTEM_CPU_INFORMATION is cached. Information
is available via NtQuerySystemInformation (SystemInformationClass:
SystemCpuInformation).
-------------- next part --------------
From eaeb9b864639ec006acd7b5516cda1ded48321c8 Mon Sep 17 00:00:00 2001
From: Rudolf Mayerhofer <rm at eightyfive.net>
Date: Fri, 1 Oct 2010 21:06:23 +0200
Subject: ntdll: Retrieve Logical Processor Information from SysFS
modified: dlls/ntdll/nt.c
---
dlls/ntdll/nt.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 209 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index ba8cbe7..f60451a 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -890,6 +890,96 @@ static inline void get_cpuinfo(SYSTEM_CPU_INFORMATION* info)
}
}
+/* Methods to pull data from SysFS (/sys) */
+static BOOL sysfs_cpu_exists(int cpu)
+{
+ static char buf[200];
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d",cpu);
+ return access(buf, F_OK) == 0;
+}
+static BOOL sysfs_cpucache_exists(int cpu, int cache)
+{
+ static char buf[200];
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d/cache/index%d",cpu,cache);
+ return access(buf, F_OK) == 0;
+}
+static BOOL sysfs_numanode_exists(int node)
+{
+ static char buf[200];
+ sprintf(buf, "/sys/devices/system/node/node%d",node);
+ return access(buf, F_OK) == 0;
+}
+static int sysfs_cpu_topology_get(int cpu, const char *type){
+ static char buf[200];
+ FILE *fd;
+ int result;
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d/topology/%s",cpu,type);
+ fd = fopen(buf,"r");
+ if(fscanf(fd,"%d",&result) != 1){
+ result = -1;
+ }
+ fclose(fd);
+ return result;
+}
+static int sysfs_cpucache_getint(int cpu, int cache, const char *type){
+ static char buf[200];
+ FILE *fd;
+ char c;
+ int res, val;
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d/cache/index%d/%s",cpu,cache,type);
+ fd = fopen(buf,"r");
+ if((res = fscanf(fd,"%d%c",&val, &c)) > 0){
+ if(res > 1){
+ switch(c){
+ case 'M':
+ val *= 1024 * 1024;
+ break;
+ case 'K':
+ val *= 1024;
+ break;
+ }
+ }
+ }else{
+ val = -1;
+ }
+ fclose(fd);
+ return val;
+}
+static int sysfs_cpucache_getmap(int cpu, int cache, const char *type){
+ static char buf[200];
+ FILE *fd;
+ int result;
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d/cache/index%d/%s",cpu,cache,type);
+ fd = fopen(buf,"r");
+ if(fscanf(fd,"%x",&result) != 1){
+ result = -1;
+ }
+ fclose(fd);
+ return result;
+}
+static BOOL sysfs_cpucache_gettype(int cpu, int cache, char* type){
+ static char buf[200];
+ FILE *fd;
+ int res;
+ sprintf(buf, "/sys/devices/system/cpu/cpu%d/cache/index%d/type",cpu,cache);
+ fd = fopen(buf,"r");
+ res = fscanf(fd,"%s",type);
+ fclose(fd);
+ return res;
+}
+static ULONG sysfs_numanode_cpumap(int node){
+ static char buf[200];
+ FILE *fd;
+ int result;
+ sprintf(buf, "/sys/devices/system/node/node%d/cpumap",node);
+ fd = fopen(buf,"r");
+ if(fscanf(fd,"%x",&result) != 1){
+ result = -1;
+ }
+ fclose(fd);
+ return result;
+}
+
/******************************************************************
* fill_cpu_info
*
@@ -1063,11 +1153,128 @@ void fill_cpu_info(void)
user_shared_data->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
if (strstr(value, "pae"))
user_shared_data->ProcessorFeatures[PF_PAE_ENABLED] = TRUE;
+ if (strstr(value, "ht"))
+ cached_sci.FeatureSet |= CPU_FEATURE_HTT;
continue;
}
- }
- fclose(f);
+ }
+ fclose(f);
+
+ /* Retrieve Logical Processor Information from SysFS */
+ {
+ int numadummymask = 0;
+ int sysfs_cpucount = 0;
+ int sysfs_nodecount = 0;
+
+ while(sysfs_cpu_exists(sysfs_cpucount))
+ {
+ sysfs_cpucount++;
+ }
+ TRACE("SysFS CPU Count: %d\n", sysfs_cpucount);
+
+ if (sysfs_cpucount > 0)
+ {
+ int cpucounter, cachecounter;
+ /* Parse every CPU's CoreID and Physical Package
+ and generate the ProcessorMask for each */
+ cpucounter = 0;
+ while(cpucounter < sysfs_cpucount)
+ {
+ int core, ppackage;
+ /* Determine Core ID and add to matching ProcessorMask */
+ core = sysfs_cpu_topology_get(cpucounter, "core_id");
+ if(core >= 0 && core < (sizeof(cached_sci.Cores) / sizeof(ULONG))){
+ numadummymask |= (1 << cpucounter);
+ cached_sci.Cores[core] |= (1 << cpucounter);
+ TRACE("Processormask on Core %d is now %d\n", core, cached_sci.Cores[core]);
+ }
+
+ /* Determine ProcessorPackage and add to matching ProcessorMask */
+ ppackage = sysfs_cpu_topology_get(cpucounter, "physical_package_id");
+ if(ppackage >= 0 && ppackage < (sizeof(cached_sci.ProcessorPackages) / sizeof(ULONG)))
+ {
+ cached_sci.ProcessorPackages[ppackage] |= (1 << cpucounter);
+ }
+
+ /* Determine CPUs Caches */
+ cachecounter = 0;
+ while(sysfs_cpucache_exists(cpucounter,cachecounter))
+ {
+ /* Get all cache information from SysFS */
+ ULONG processormask = sysfs_cpucache_getmap(cpucounter,cachecounter,"shared_cpu_map");
+ BYTE level = sysfs_cpucache_getint(cpucounter,cachecounter,"level");
+ BYTE associativity = sysfs_cpucache_getint(cpucounter,cachecounter,"ways_of_associativity");
+ WORD linesize = sysfs_cpucache_getint(cpucounter,cachecounter,"coherency_line_size");
+ DWORD size = sysfs_cpucache_getint(cpucounter,cachecounter,"size");
+ PROCESSOR_CACHE_TYPE type = 0;
+ char typestring[16];
+ if (sysfs_cpucache_gettype(cpucounter,cachecounter,typestring) > 0)
+ {
+ switch(typestring[0]){
+ case 'D':
+ type = CacheData;
+ break;
+ case 'I':
+ type = CacheInstruction;
+ break;
+ case 'U':
+ type = CacheUnified;
+ break;
+ case 'T':
+ type = CacheTrace;
+ break;
+ default:
+ FIXME("Unknown cachetype %s", typestring);
+ break;
+ }
+
+ /* Iterate the array ... */
+ {
+ int arraycounter = 0;
+ while(arraycounter < (sizeof(cached_sci) / sizeof(SYSTEM_CPU_CACHE_INFORMATION)))
+ {
+ if(cached_sci.Caches[arraycounter].ProcessorMask == 0)
+ {
+ /* ... and add the entry at the first free position */
+ cached_sci.Caches[arraycounter].ProcessorMask = processormask;
+ cached_sci.Caches[arraycounter].CacheInformation.Level = level;
+ cached_sci.Caches[arraycounter].CacheInformation.Associativity = associativity;
+ cached_sci.Caches[arraycounter].CacheInformation.LineSize = linesize;
+ cached_sci.Caches[arraycounter].CacheInformation.Size = size;
+ cached_sci.Caches[arraycounter].CacheInformation.Type = type;
+ break;
+ }
+ else if(cached_sci.Caches[arraycounter].ProcessorMask == processormask && cached_sci.Caches[arraycounter].CacheInformation.Level == level && cached_sci.Caches[arraycounter].CacheInformation.Type == type)
+ {
+ /* ... and ignore entry because it already exists */
+ break;
+ }
+ else
+ {
+ arraycounter++;
+ }
+ }
+ }
+ }
+ cachecounter++;
+ }
+ /* Next CPU */
+ cpucounter++;
+ }
+ /* Determine Numa Nodes */
+ while(sysfs_numanode_exists(sysfs_nodecount))
+ {
+ cached_sci.NumaNodes[sysfs_nodecount] = sysfs_numanode_cpumap(sysfs_nodecount);
+ sysfs_nodecount++;
+ }
+ /* If this is a non-numa system add a dummy */
+ if(sysfs_nodecount == 0 && !sysfs_numanode_exists(sysfs_nodecount))
+ {
+ cached_sci.NumaNodes[0] = numadummymask;
+ }
+ }
+ }
}
#elif defined (__NetBSD__)
{
--
1.7.3
More information about the wine-patches
mailing list