blob: 2b0a36ebf27a3aa13df0b3dd56e2cff94a372d55 [file] [log] [blame]
Andi Kleende5077c2017-08-11 16:26:22 -07001#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <linux/bitops.h>
5#include "api/fs/fs.h"
6#include "smt.h"
7
Ian Rogers0ce05782021-11-23 16:12:30 -08008/**
9 * hweight_str - Returns the number of bits set in str. Stops at first non-hex
10 * or ',' character.
11 */
12static 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 }
54done:
55 return result;
56}
57
Andi Kleende5077c2017-08-11 16:26:22 -070058int smt_on(void)
59{
60 static bool cached;
61 static int cached_result;
62 int cpu;
63 int ncpu;
64
65 if (cached)
66 return cached_result;
67
Ian Rogers0ce05782021-11-23 16:12:30 -080068 if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) {
69 cached = true;
70 return cached_result;
71 }
Konstantin Khlebnikovbb629482020-04-29 19:23:41 +030072
Ian Rogers0ce05782021-11-23 16:12:30 -080073 cached_result = 0;
Andi Kleende5077c2017-08-11 16:26:22 -070074 ncpu = sysconf(_SC_NPROCESSORS_CONF);
75 for (cpu = 0; cpu < ncpu; cpu++) {
76 unsigned long long siblings;
77 char *str;
78 size_t strlen;
79 char fn[256];
80
81 snprintf(fn, sizeof fn,
Ian Rogers6dd86462021-11-23 16:12:31 -080082 "devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
Konstantin Khlebnikov846de432020-04-29 19:19:47 +030083 if (sysfs__read_str(fn, &str, &strlen) < 0) {
Kan Liang0ccdb842019-06-04 15:50:44 -070084 snprintf(fn, sizeof fn,
Ian Rogers6dd86462021-11-23 16:12:31 -080085 "devices/system/cpu/cpu%d/topology/core_cpus", cpu);
Konstantin Khlebnikov846de432020-04-29 19:19:47 +030086 if (sysfs__read_str(fn, &str, &strlen) < 0)
87 continue;
Kan Liang0ccdb842019-06-04 15:50:44 -070088 }
Andi Kleende5077c2017-08-11 16:26:22 -070089 /* Entry is hex, but does not have 0x, so need custom parser */
Ian Rogers0ce05782021-11-23 16:12:30 -080090 siblings = hweight_str(str);
Andi Kleende5077c2017-08-11 16:26:22 -070091 free(str);
Ian Rogers0ce05782021-11-23 16:12:30 -080092 if (siblings > 1) {
Andi Kleende5077c2017-08-11 16:26:22 -070093 cached_result = 1;
Andi Kleende5077c2017-08-11 16:26:22 -070094 break;
95 }
96 }
Ian Rogers0ce05782021-11-23 16:12:30 -080097 cached = true;
Andi Kleende5077c2017-08-11 16:26:22 -070098 return cached_result;
99}