1
2
3
4
5
6
7
8
9
10
11
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <errno.h>
17#include <fcntl.h>
18
19#include <helpers/helpers.h>
20#include <helpers/sysfs.h>
21
22
23static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
24{
25 char linebuf[MAX_LINE_LEN];
26 char *endp;
27 char path[SYSFS_PATH_MAX];
28
29 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
30 cpu, fname);
31 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
32 return -1;
33 *result = strtol(linebuf, &endp, 0);
34 if (endp == linebuf || errno == ERANGE)
35 return -1;
36 return 0;
37}
38
39static int __compare(const void *t1, const void *t2)
40{
41 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
42 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
43 if (top1->pkg < top2->pkg)
44 return -1;
45 else if (top1->pkg > top2->pkg)
46 return 1;
47 else if (top1->core < top2->core)
48 return -1;
49 else if (top1->core > top2->core)
50 return 1;
51 else if (top1->cpu < top2->cpu)
52 return -1;
53 else if (top1->cpu > top2->cpu)
54 return 1;
55 else
56 return 0;
57}
58
59
60
61
62
63
64
65int get_cpu_topology(struct cpupower_topology *cpu_top)
66{
67 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
68
69 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
70 if (cpu_top->core_info == NULL)
71 return -ENOMEM;
72 cpu_top->pkgs = cpu_top->cores = 0;
73 for (cpu = 0; cpu < cpus; cpu++) {
74 cpu_top->core_info[cpu].cpu = cpu;
75 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
76 if(sysfs_topology_read_file(
77 cpu,
78 "physical_package_id",
79 &(cpu_top->core_info[cpu].pkg)) < 0)
80 return -1;
81 if(sysfs_topology_read_file(
82 cpu,
83 "core_id",
84 &(cpu_top->core_info[cpu].core)) < 0)
85 return -1;
86 }
87
88 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
89 __compare);
90
91
92
93
94 last_pkg = cpu_top->core_info[0].pkg;
95 for(cpu = 1; cpu < cpus; cpu++) {
96 if(cpu_top->core_info[cpu].pkg != last_pkg) {
97 last_pkg = cpu_top->core_info[cpu].pkg;
98 cpu_top->pkgs++;
99 }
100 }
101 cpu_top->pkgs++;
102
103
104
105
106
107
108
109
110 return cpus;
111}
112
113void cpu_topology_release(struct cpupower_topology cpu_top)
114{
115 free(cpu_top.core_info);
116}
117