2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
22 #include <rte_lcore.h>
24 #include "cpu_core_map.h"
27 uint32_t n_max_sockets;
28 uint32_t n_max_cores_per_socket;
29 uint32_t n_max_ht_per_core;
31 uint32_t n_cores_per_socket;
32 uint32_t n_ht_per_core;
36 static inline uint32_t
37 cpu_core_map_pos(struct cpu_core_map *map,
42 return (socket_id * map->n_max_cores_per_socket + core_id) *
43 map->n_max_ht_per_core + ht_id;
47 cpu_core_map_compute_eal(struct cpu_core_map *map);
50 cpu_core_map_compute_linux(struct cpu_core_map *map);
53 cpu_core_map_compute_and_check(struct cpu_core_map *map);
56 cpu_core_map_init(uint32_t n_max_sockets,
57 uint32_t n_max_cores_per_socket,
58 uint32_t n_max_ht_per_core,
59 uint32_t eal_initialized)
61 uint32_t map_size, map_mem_size, i;
62 struct cpu_core_map *map;
65 /* Check input arguments */
66 if ((n_max_sockets == 0) ||
67 (n_max_cores_per_socket == 0) ||
68 (n_max_ht_per_core == 0))
71 /* Memory allocation */
72 map_size = n_max_sockets * n_max_cores_per_socket * n_max_ht_per_core;
73 map_mem_size = sizeof(struct cpu_core_map) + map_size * sizeof(int);
74 map = (struct cpu_core_map *) malloc(map_mem_size);
79 map->n_max_sockets = n_max_sockets;
80 map->n_max_cores_per_socket = n_max_cores_per_socket;
81 map->n_max_ht_per_core = n_max_ht_per_core;
83 map->n_cores_per_socket = 0;
84 map->n_ht_per_core = 0;
86 for (i = 0; i < map_size; i++)
89 status = (eal_initialized) ?
90 cpu_core_map_compute_eal(map) :
91 cpu_core_map_compute_linux(map);
98 status = cpu_core_map_compute_and_check(map);
108 cpu_core_map_compute_eal(struct cpu_core_map *map)
110 uint32_t socket_id, core_id, ht_id;
113 for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) {
114 uint32_t n_detected, core_id_contig;
118 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
119 struct lcore_config *p = &lcore_config[lcore_id];
121 if ((p->detected) && (p->socket_id == socket_id))
127 for (core_id = 0; n_detected ; core_id++) {
131 lcore_id < RTE_MAX_LCORE;
133 struct lcore_config *p =
134 &lcore_config[lcore_id];
137 (p->socket_id == socket_id) &&
138 (p->core_id == core_id)) {
139 uint32_t pos = cpu_core_map_pos(map,
144 map->map[pos] = lcore_id;
152 if (core_id_contig ==
153 map->n_max_cores_per_socket)
163 cpu_core_map_compute_and_check(struct cpu_core_map *map)
165 uint32_t socket_id, core_id, ht_id;
167 /* Compute n_ht_per_core, n_cores_per_socket, n_sockets */
168 for (ht_id = 0; ht_id < map->n_max_ht_per_core; ht_id++) {
169 if (map->map[ht_id] == -1)
172 map->n_ht_per_core++;
175 if (map->n_ht_per_core == 0)
178 for (core_id = 0; core_id < map->n_max_cores_per_socket; core_id++) {
179 uint32_t pos = core_id * map->n_max_ht_per_core;
181 if (map->map[pos] == -1)
184 map->n_cores_per_socket++;
187 if (map->n_cores_per_socket == 0)
190 for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) {
191 uint32_t pos = socket_id * map->n_max_cores_per_socket *
192 map->n_max_ht_per_core;
194 if (map->map[pos] == -1)
200 if (map->n_sockets == 0)
203 /* Check that each socket has exactly the same number of cores
204 and that each core has exactly the same number of hyper-threads */
205 for (socket_id = 0; socket_id < map->n_sockets; socket_id++) {
206 for (core_id = 0; core_id < map->n_cores_per_socket; core_id++)
208 ht_id < map->n_max_ht_per_core;
210 uint32_t pos = (socket_id *
211 map->n_max_cores_per_socket + core_id) *
212 map->n_max_ht_per_core + ht_id;
214 if (((ht_id < map->n_ht_per_core) &&
215 (map->map[pos] == -1)) ||
216 ((ht_id >= map->n_ht_per_core) &&
217 (map->map[pos] != -1)))
221 for ( ; core_id < map->n_max_cores_per_socket; core_id++)
223 ht_id < map->n_max_ht_per_core;
225 uint32_t pos = cpu_core_map_pos(map,
230 if (map->map[pos] != -1)
238 #define FILE_LINUX_CPU_N_LCORES \
239 "/sys/devices/system/cpu/present"
242 cpu_core_map_get_n_lcores_linux(void)
244 char buffer[64], *string;
247 fd = fopen(FILE_LINUX_CPU_N_LCORES, "r");
251 if (fgets(buffer, sizeof(buffer), fd) == NULL) {
258 string = index(buffer, '-');
262 return atoi(++string) + 1;
265 #define FILE_LINUX_CPU_CORE_ID \
266 "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_id"
269 cpu_core_map_get_core_id_linux(int lcore_id)
275 snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_CORE_ID, lcore_id);
276 fd = fopen(buffer, "r");
280 if (fgets(buffer, sizeof(buffer), fd) == NULL) {
287 core_id = atoi(buffer);
291 #define FILE_LINUX_CPU_SOCKET_ID \
292 "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/physical_package_id"
295 cpu_core_map_get_socket_id_linux(int lcore_id)
301 snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_SOCKET_ID, lcore_id);
302 fd = fopen(buffer, "r");
306 if (fgets(buffer, sizeof(buffer), fd) == NULL) {
313 socket_id = atoi(buffer);
318 cpu_core_map_compute_linux(struct cpu_core_map *map)
320 uint32_t socket_id, core_id, ht_id;
323 n_lcores = cpu_core_map_get_n_lcores_linux();
328 for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) {
329 uint32_t n_detected, core_id_contig;
333 for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) {
334 int lcore_socket_id =
335 cpu_core_map_get_socket_id_linux(lcore_id);
337 if (lcore_socket_id < 0)
340 if (((uint32_t) lcore_socket_id) == socket_id)
346 for (core_id = 0; n_detected ; core_id++) {
349 for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) {
350 int lcore_socket_id =
351 cpu_core_map_get_socket_id_linux(
354 if (lcore_socket_id < 0)
358 cpu_core_map_get_core_id_linux(
361 if (lcore_core_id < 0)
364 if (((uint32_t) lcore_socket_id == socket_id) &&
365 ((uint32_t) lcore_core_id == core_id)) {
366 uint32_t pos = cpu_core_map_pos(map,
371 map->map[pos] = lcore_id;
379 if (core_id_contig ==
380 map->n_max_cores_per_socket)
390 cpu_core_map_print(struct cpu_core_map *map)
392 uint32_t socket_id, core_id, ht_id;
397 for (socket_id = 0; socket_id < map->n_sockets; socket_id++) {
398 printf("Socket %" PRIu32 ":\n", socket_id);
401 core_id < map->n_cores_per_socket;
403 printf("[%" PRIu32 "] = [", core_id);
405 for (ht_id = 0; ht_id < map->n_ht_per_core; ht_id++) {
406 int lcore_id = cpu_core_map_get_lcore_id(map,
411 uint32_t core_id_noncontig =
412 cpu_core_map_get_core_id_linux(
415 printf(" %" PRId32 " (%" PRIu32 ") ",
426 cpu_core_map_get_n_sockets(struct cpu_core_map *map)
431 return map->n_sockets;
435 cpu_core_map_get_n_cores_per_socket(struct cpu_core_map *map)
440 return map->n_cores_per_socket;
444 cpu_core_map_get_n_ht_per_core(struct cpu_core_map *map)
449 return map->n_ht_per_core;
453 cpu_core_map_get_lcore_id(struct cpu_core_map *map,
461 (socket_id >= map->n_sockets) ||
462 (core_id >= map->n_cores_per_socket) ||
463 (ht_id >= map->n_ht_per_core))
466 pos = cpu_core_map_pos(map, socket_id, core_id, ht_id);
468 return map->map[pos];
472 cpu_core_map_free(struct cpu_core_map *map)