Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Fix SMT fallback with large core counts

strtoull can only read a 64-bit bitmap. On an AMD EPYC core_cpus may look
like:

00000000,00000000,00000000,00000001,00000000,00000000,00000000,00000001

and so the sibling wasn't spotted. Fix by writing a simple hweight string
parser.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: John Garry <john.garry@huawei.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: https://lore.kernel.org/r/20211124001231.3277836-3-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
0ce05781 6d18804b

+58 -10
+58 -10
tools/perf/util/smt.c
··· 5 5 #include "api/fs/fs.h" 6 6 #include "smt.h" 7 7 8 + /** 9 + * hweight_str - Returns the number of bits set in str. Stops at first non-hex 10 + * or ',' character. 11 + */ 12 + static int hweight_str(char *str) 13 + { 14 + int result = 0; 15 + 16 + while (*str) { 17 + switch (*str++) { 18 + case '0': 19 + case ',': 20 + break; 21 + case '1': 22 + case '2': 23 + case '4': 24 + case '8': 25 + result++; 26 + break; 27 + case '3': 28 + case '5': 29 + case '6': 30 + case '9': 31 + case 'a': 32 + case 'A': 33 + case 'c': 34 + case 'C': 35 + result += 2; 36 + break; 37 + case '7': 38 + case 'b': 39 + case 'B': 40 + case 'd': 41 + case 'D': 42 + case 'e': 43 + case 'E': 44 + result += 3; 45 + break; 46 + case 'f': 47 + case 'F': 48 + result += 4; 49 + break; 50 + default: 51 + goto done; 52 + } 53 + } 54 + done: 55 + return result; 56 + } 57 + 8 58 int smt_on(void) 9 59 { 10 60 static bool cached; ··· 65 15 if (cached) 66 16 return cached_result; 67 17 68 - if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) 69 - goto done; 18 + if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) { 19 + cached = true; 20 + return cached_result; 21 + } 70 22 23 + cached_result = 0; 71 24 ncpu = sysconf(_SC_NPROCESSORS_CONF); 72 25 for (cpu = 0; cpu < ncpu; cpu++) { 73 26 unsigned long long siblings; ··· 88 35 continue; 89 36 } 90 37 /* Entry is hex, but does not have 0x, so need custom parser */ 91 - siblings = strtoull(str, NULL, 16); 38 + siblings = hweight_str(str); 92 39 free(str); 93 - if (hweight64(siblings) > 1) { 40 + if (siblings > 1) { 94 41 cached_result = 1; 95 - cached = true; 96 42 break; 97 43 } 98 44 } 99 - if (!cached) { 100 - cached_result = 0; 101 - done: 102 - cached = true; 103 - } 45 + cached = true; 104 46 return cached_result; 105 47 }