0001 #include <stdio.h>
0002 #include <stdlib.h>
0003 #include <unistd.h>
0004 #include <linux/bitops.h>
0005 #include "api/fs/fs.h"
0006 #include "smt.h"
0007
0008
0009
0010
0011
0012 static int hweight_str(char *str)
0013 {
0014 int result = 0;
0015
0016 while (*str) {
0017 switch (*str++) {
0018 case '0':
0019 case ',':
0020 break;
0021 case '1':
0022 case '2':
0023 case '4':
0024 case '8':
0025 result++;
0026 break;
0027 case '3':
0028 case '5':
0029 case '6':
0030 case '9':
0031 case 'a':
0032 case 'A':
0033 case 'c':
0034 case 'C':
0035 result += 2;
0036 break;
0037 case '7':
0038 case 'b':
0039 case 'B':
0040 case 'd':
0041 case 'D':
0042 case 'e':
0043 case 'E':
0044 result += 3;
0045 break;
0046 case 'f':
0047 case 'F':
0048 result += 4;
0049 break;
0050 default:
0051 goto done;
0052 }
0053 }
0054 done:
0055 return result;
0056 }
0057
0058 int smt_on(void)
0059 {
0060 static bool cached;
0061 static int cached_result;
0062 int cpu;
0063 int ncpu;
0064
0065 if (cached)
0066 return cached_result;
0067
0068 if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) {
0069 cached = true;
0070 return cached_result;
0071 }
0072
0073 cached_result = 0;
0074 ncpu = sysconf(_SC_NPROCESSORS_CONF);
0075 for (cpu = 0; cpu < ncpu; cpu++) {
0076 unsigned long long siblings;
0077 char *str;
0078 size_t strlen;
0079 char fn[256];
0080
0081 snprintf(fn, sizeof fn,
0082 "devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
0083 if (sysfs__read_str(fn, &str, &strlen) < 0) {
0084 snprintf(fn, sizeof fn,
0085 "devices/system/cpu/cpu%d/topology/core_cpus", cpu);
0086 if (sysfs__read_str(fn, &str, &strlen) < 0)
0087 continue;
0088 }
0089
0090 siblings = hweight_str(str);
0091 free(str);
0092 if (siblings > 1) {
0093 cached_result = 1;
0094 break;
0095 }
0096 }
0097 cached = true;
0098 return cached_result;
0099 }