1 #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 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 58 int 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 68 if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) { 69 cached = true; 70 return cached_result; 71 } 72 73 cached_result = 0; 74 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, 82 "devices/system/cpu/cpu%d/topology/thread_siblings", cpu); 83 if (sysfs__read_str(fn, &str, &strlen) < 0) { 84 snprintf(fn, sizeof fn, 85 "devices/system/cpu/cpu%d/topology/core_cpus", cpu); 86 if (sysfs__read_str(fn, &str, &strlen) < 0) 87 continue; 88 } 89 /* Entry is hex, but does not have 0x, so need custom parser */ 90 siblings = hweight_str(str); 91 free(str); 92 if (siblings > 1) { 93 cached_result = 1; 94 break; 95 } 96 } 97 cached = true; 98 return cached_result; 99 } 100