diff --git a/src/common/udev.c b/src/common/udev.c index 66c1d52..d1c41ac 100644 --- a/src/common/udev.c +++ b/src/common/udev.c @@ -278,3 +278,99 @@ int get_num_caches_by_level(struct cpuInfo* cpu, uint32_t level) { return ret; } + +// TODO: This function is very similar to get_num_caches_from_files, +// refactoring should be considered +int get_num_sockets_from_files(char** paths, int num_paths) { + int filelen; + char* buf; + char* tmpbuf; + + // 1. Count the number of bitmasks per file + if((buf = read_file(paths[0], &filelen)) == NULL) { + printWarn("Could not open '%s'", paths[0]); + return -1; + } + int num_bitmasks = 1; + for(int i=0; buf[i]; i++) { + num_bitmasks += (buf[i] == ','); + } + + // 2. Read package_cpus from every core + uint32_t** package_cpus = emalloc(sizeof(uint32_t *) * num_paths); + for(int i=0; i < num_paths; i++) { + package_cpus[i] = emalloc(sizeof(uint32_t) * num_bitmasks); + + if((buf = read_file(paths[i], &filelen)) == NULL) { + printWarn("Could not open '%s'", paths[i]); + return -1; + } + + for(int j=0; j < num_bitmasks; j++) { + char* end; + tmpbuf = emalloc(sizeof(char) * (strlen(buf) + 1)); + char* commaend = strstr(buf, ","); + if(commaend == NULL) { + strcpy(tmpbuf, buf); + } + else { + strncpy(tmpbuf, buf, commaend-buf); + } + errno = 0; + long ret = strtol(tmpbuf, &end, 16); + if(errno != 0) { + printf("strtol: %s", strerror(errno)); + free(buf); + return -1; + } + + package_cpus[i][j] = (uint32_t) ret; + buf = commaend + 1; + free(tmpbuf); + } + } + + // 3. Count number of different packages; this is the number of sockets + int num_sockets = 0; + bool found = false; + uint32_t** unique_package_cpu = emalloc(sizeof(uint32_t *) * num_paths); + for(int i=0; i < num_paths; i++) { + unique_package_cpu[i] = emalloc(sizeof(uint32_t) * num_bitmasks); + for(int j=0; j < num_bitmasks; j++) { + unique_package_cpu[i][j] = 0; + } + } + + for(int i=0; i < num_paths; i++) { + for(int j=0; j < num_paths && !found; j++) { + if(maps_equal(package_cpus[i], unique_package_cpu[j], num_bitmasks)) found = true; + } + if(!found) { + add_shared_map(package_cpus, i, unique_package_cpu, num_sockets, num_bitmasks); + num_sockets++; + } + found = false; + } + + return num_sockets; +} + +int get_num_sockets_package_cpus(struct topology* topo) { + // Get number of sockets using + // /sys/devices/system/cpu/cpu*/topology/package_cpus + + char** paths = emalloc(sizeof(char *) * topo->total_cores); + + for(int i=0; i < topo->total_cores; i++) { + paths[i] = emalloc(sizeof(char) * _PATH_PACKAGE_MAX_LEN); + sprintf(paths[i], "%s%s/cpu%d%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, i, _PATH_TOPO_PACKAGE_CPUS); + } + + int ret = get_num_sockets_from_files(paths, topo->total_cores); + + for(int i=0; i < topo->total_cores; i++) + free(paths[i]); + free(paths); + + return ret; +} diff --git a/src/common/udev.h b/src/common/udev.h index bf83493..d0a4739 100644 --- a/src/common/udev.h +++ b/src/common/udev.h @@ -23,10 +23,12 @@ #define _PATH_CACHE_L3 "/cache/index3" #define _PATH_CACHE_SIZE "/size" #define _PATH_CACHE_SHARED_MAP "/shared_cpu_map" -#define _PATH_CPUS_PRESENT _PATH_SYS_SYSTEM _PATH_SYS_CPU "/present" +#define _PATH_CPUS_PRESENT _PATH_SYS_SYSTEM _PATH_SYS_CPU "/present" +#define _PATH_TOPO_PACKAGE_CPUS "/topology/package_cpus" #define _PATH_FREQUENCY_MAX_LEN 100 #define _PATH_CACHE_MAX_LEN 200 +#define _PATH_PACKAGE_MAX_LEN 200 char* read_file(char* path, int* len); long get_max_freq_from_file(uint32_t core); @@ -36,6 +38,7 @@ long get_l1d_cache_size(uint32_t core); long get_l2_cache_size(uint32_t core); long get_l3_cache_size(uint32_t core); int get_num_caches_by_level(struct cpuInfo* cpu, uint32_t level); +int get_num_sockets_package_cpus(struct topology* topo); int get_ncores_from_cpuinfo(void); #endif diff --git a/src/ppc/ppc.c b/src/ppc/ppc.c index 70a9df5..c2a31d6 100644 --- a/src/ppc/ppc.c +++ b/src/ppc/ppc.c @@ -44,17 +44,6 @@ struct cache* get_cache_info(struct cpuInfo* cpu) { return cach; } -bool check_package_ids_integrity(int* package_ids, int total_cores) { - for(int i=0; i < total_cores; i++) { - if(package_ids[i] >= total_cores || package_ids[i] < 0) { - printBug("check_package_ids_integrity: package_ids[%d]=%d", i, package_ids[i]); - return false; - } - } - - return true; -} - struct topology* get_topology_info(struct cache* cach) { struct topology* topo = emalloc(sizeof(struct topology)); init_topology_struct(topo, cach); @@ -74,27 +63,30 @@ struct topology* get_topology_info(struct cache* cach) { printWarn("fill_core_ids_from_sys failed, output may be incomplete/invalid"); for(int i=0; i < topo->total_cores; i++) core_ids[i] = 0; } + if(!fill_package_ids_from_sys(package_ids, topo->total_cores)) { printWarn("fill_package_ids_from_sys failed, output may be incomplete/invalid"); for(int i=0; i < topo->total_cores; i++) package_ids[i] = 0; + // fill_package_ids_from_sys failed, use a + // more sophisticated wat to find the number of sockets + topo->sockets = get_num_sockets_package_cpus(topo); } - - if(!check_package_ids_integrity(package_ids, topo->total_cores)) { - return NULL; - } - - // 2. Socket detection - int *package_ids_count = emalloc(sizeof(int) * topo->total_cores); - for(int i=0; i < topo->total_cores; i++) { - package_ids_count[i] = 0; - } - for(int i=0; i < topo->total_cores; i++) { - package_ids_count[package_ids[i]]++; - } - for(int i=0; i < topo->total_cores; i++) { - if(package_ids_count[i] != 0) { - topo->sockets++; + else { + // fill_package_ids_from_sys succeeded, use the + // traditional socket detection algorithm + int *package_ids_count = emalloc(sizeof(int) * topo->total_cores); + for(int i=0; i < topo->total_cores; i++) { + package_ids_count[i] = 0; } + for(int i=0; i < topo->total_cores; i++) { + package_ids_count[package_ids[i]]++; + } + for(int i=0; i < topo->total_cores; i++) { + if(package_ids_count[i] != 0) { + topo->sockets++; + } + } + free(package_ids_count); } // 3. Physical cores detection @@ -120,7 +112,6 @@ struct topology* get_topology_info(struct cache* cach) { free(core_ids); free(package_ids); - free(package_ids_count); free(core_ids_unified); return topo; @@ -187,7 +178,9 @@ struct cpuInfo* get_cpu_info(void) { char* path = emalloc(sizeof(char) * (strlen(_PATH_DT) + strlen(_PATH_DT_PART) + 1)); sprintf(path, "%s%s", _PATH_DT, _PATH_DT_PART); - cpu->cpu_name = read_file(path, &len); + if((cpu->cpu_name = read_file(path, &len)) == NULL) { + printWarn("Could not open '%s'", path); + } cpu->pvr = mfpvr(); cpu->arch = get_cpu_uarch(cpu); cpu->freq = get_frequency_info(); diff --git a/src/ppc/udev.c b/src/ppc/udev.c index 315d7d7..3313e64 100644 --- a/src/ppc/udev.c +++ b/src/ppc/udev.c @@ -1,16 +1,18 @@ #include +#include "../common/udev.h" #include "../common/global.h" #include "udev.h" -#define _PATH_TOPO_CORE_ID "topology/core_id" -#define _PATH_TOPO_PACKAGE_ID "topology/physical_package_id" +#define _PATH_TOPO_CORE_ID "topology/core_id" +#define _PATH_TOPO_PACKAGE_ID "topology/physical_package_id" bool fill_array_from_sys(int *core_ids, int total_cores, char* SYS_PATH) { int filelen; char* buf; char* end; char path[128]; + memset(path, 0, 128); for(int i=0; i < total_cores; i++) { sprintf(path, "%s%s/cpu%d/%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, i, SYS_PATH); @@ -36,5 +38,22 @@ bool fill_core_ids_from_sys(int *core_ids, int total_cores) { } bool fill_package_ids_from_sys(int* package_ids, int total_cores) { - return fill_array_from_sys(package_ids, total_cores, _PATH_TOPO_PACKAGE_ID); + bool status = fill_array_from_sys(package_ids, total_cores, _PATH_TOPO_PACKAGE_ID); + if(status) { + // fill_array_from_sys completed successfully, but we + // must to check the integrity of the package_ids array + for(int i=0; i < total_cores; i++) { + if(package_ids[i] == -1) { + printWarn("fill_package_ids_from_sys: package_ids[%d] = -1", i); + return false; + } + else if(package_ids[i] >= total_cores || package_ids[i] < 0) { + printBug("fill_package_ids_from_sys: package_ids[%d] = %d", i, package_ids[i]); + return false; + } + } + + return true; + } + return false; } diff --git a/src/ppc/udev.h b/src/ppc/udev.h index 8c21875..5452382 100644 --- a/src/ppc/udev.h +++ b/src/ppc/udev.h @@ -7,5 +7,6 @@ bool fill_core_ids_from_sys(int *core_ids, int total_cores); bool fill_package_ids_from_sys(int* package_ids, int total_cores); +int get_num_sockets_package_cpus(struct topology* topo); #endif