#include #include #include #include #include "api/fs/fs.h" #include "smt.h" /** * hweight_str - Returns the number of bits set in str. Stops at first non-hex * or ',' character. */ static int hweight_str(char *str) { int result = 0; while (*str) { switch (*str++) { case '0': case ',': break; case '1': case '2': case '4': case '8': result++; break; case '3': case '5': case '6': case '9': case 'a': case 'A': case 'c': case 'C': result += 2; break; case '7': case 'b': case 'B': case 'd': case 'D': case 'e': case 'E': result += 3; break; case 'f': case 'F': result += 4; break; default: goto done; } } done: return result; } int smt_on(void) { static bool cached; static int cached_result; int cpu; int ncpu; if (cached) return cached_result; if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) { cached = true; return cached_result; } cached_result = 0; ncpu = sysconf(_SC_NPROCESSORS_CONF); for (cpu = 0; cpu < ncpu; cpu++) { unsigned long long siblings; char *str; size_t strlen; char fn[256]; snprintf(fn, sizeof fn, "devices/system/cpu/cpu%d/topology/thread_siblings", cpu); if (sysfs__read_str(fn, &str, &strlen) < 0) { snprintf(fn, sizeof fn, "devices/system/cpu/cpu%d/topology/core_cpus", cpu); if (sysfs__read_str(fn, &str, &strlen) < 0) continue; } /* Entry is hex, but does not have 0x, so need custom parser */ siblings = hweight_str(str); free(str); if (siblings > 1) { cached_result = 1; break; } } cached = true; return cached_result; }