[v1.03][PPC] Fix bug where /sys/devices/system/cpu/cpu*/topology/physical_package_id contains -1 by adding a new way of finding the number of sockets. This happened in #178 and most probably in #153 too

This commit is contained in:
Dr-Noob
2023-05-03 17:51:44 +02:00
parent 8c72295f47
commit ebe7312c9d
5 changed files with 145 additions and 33 deletions

View File

@@ -278,3 +278,99 @@ int get_num_caches_by_level(struct cpuInfo* cpu, uint32_t level) {
return ret; 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;
}

View File

@@ -23,10 +23,12 @@
#define _PATH_CACHE_L3 "/cache/index3" #define _PATH_CACHE_L3 "/cache/index3"
#define _PATH_CACHE_SIZE "/size" #define _PATH_CACHE_SIZE "/size"
#define _PATH_CACHE_SHARED_MAP "/shared_cpu_map" #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_FREQUENCY_MAX_LEN 100
#define _PATH_CACHE_MAX_LEN 200 #define _PATH_CACHE_MAX_LEN 200
#define _PATH_PACKAGE_MAX_LEN 200
char* read_file(char* path, int* len); char* read_file(char* path, int* len);
long get_max_freq_from_file(uint32_t core); 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_l2_cache_size(uint32_t core);
long get_l3_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_caches_by_level(struct cpuInfo* cpu, uint32_t level);
int get_num_sockets_package_cpus(struct topology* topo);
int get_ncores_from_cpuinfo(void); int get_ncores_from_cpuinfo(void);
#endif #endif

View File

@@ -44,17 +44,6 @@ struct cache* get_cache_info(struct cpuInfo* cpu) {
return cach; 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* get_topology_info(struct cache* cach) {
struct topology* topo = emalloc(sizeof(struct topology)); struct topology* topo = emalloc(sizeof(struct topology));
init_topology_struct(topo, cach); 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"); 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; for(int i=0; i < topo->total_cores; i++) core_ids[i] = 0;
} }
if(!fill_package_ids_from_sys(package_ids, topo->total_cores)) { if(!fill_package_ids_from_sys(package_ids, topo->total_cores)) {
printWarn("fill_package_ids_from_sys failed, output may be incomplete/invalid"); 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; 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);
} }
else {
if(!check_package_ids_integrity(package_ids, topo->total_cores)) { // fill_package_ids_from_sys succeeded, use the
return NULL; // traditional socket detection algorithm
} int *package_ids_count = emalloc(sizeof(int) * topo->total_cores);
for(int i=0; i < topo->total_cores; i++) {
// 2. Socket detection package_ids_count[i] = 0;
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++;
} }
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 // 3. Physical cores detection
@@ -120,7 +112,6 @@ struct topology* get_topology_info(struct cache* cach) {
free(core_ids); free(core_ids);
free(package_ids); free(package_ids);
free(package_ids_count);
free(core_ids_unified); free(core_ids_unified);
return topo; 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)); char* path = emalloc(sizeof(char) * (strlen(_PATH_DT) + strlen(_PATH_DT_PART) + 1));
sprintf(path, "%s%s", _PATH_DT, _PATH_DT_PART); 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->pvr = mfpvr();
cpu->arch = get_cpu_uarch(cpu); cpu->arch = get_cpu_uarch(cpu);
cpu->freq = get_frequency_info(); cpu->freq = get_frequency_info();

View File

@@ -1,16 +1,18 @@
#include <errno.h> #include <errno.h>
#include "../common/udev.h"
#include "../common/global.h" #include "../common/global.h"
#include "udev.h" #include "udev.h"
#define _PATH_TOPO_CORE_ID "topology/core_id" #define _PATH_TOPO_CORE_ID "topology/core_id"
#define _PATH_TOPO_PACKAGE_ID "topology/physical_package_id" #define _PATH_TOPO_PACKAGE_ID "topology/physical_package_id"
bool fill_array_from_sys(int *core_ids, int total_cores, char* SYS_PATH) { bool fill_array_from_sys(int *core_ids, int total_cores, char* SYS_PATH) {
int filelen; int filelen;
char* buf; char* buf;
char* end; char* end;
char path[128]; char path[128];
memset(path, 0, 128);
for(int i=0; i < total_cores; i++) { for(int i=0; i < total_cores; i++) {
sprintf(path, "%s%s/cpu%d/%s", _PATH_SYS_SYSTEM, _PATH_SYS_CPU, i, SYS_PATH); 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) { 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;
} }

View File

@@ -7,5 +7,6 @@
bool fill_core_ids_from_sys(int *core_ids, int total_cores); bool fill_core_ids_from_sys(int *core_ids, int total_cores);
bool fill_package_ids_from_sys(int* package_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 #endif