4 * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <rte_lcore.h>
41 #include "cpu_core_map.h"
44 uint32_t n_max_sockets;
45 uint32_t n_max_cores_per_socket;
46 uint32_t n_max_ht_per_core;
48 uint32_t n_cores_per_socket;
49 uint32_t n_ht_per_core;
53 static inline uint32_t
54 cpu_core_map_pos(struct cpu_core_map *map,
59 return (socket_id * map->n_max_cores_per_socket + core_id) *
60 map->n_max_ht_per_core + ht_id;
64 cpu_core_map_compute_eal(struct cpu_core_map *map);
67 cpu_core_map_compute_linux(struct cpu_core_map *map);
70 cpu_core_map_compute_and_check(struct cpu_core_map *map);
73 cpu_core_map_init(uint32_t n_max_sockets,
74 uint32_t n_max_cores_per_socket,
75 uint32_t n_max_ht_per_core,
76 uint32_t eal_initialized)
78 uint32_t map_size, map_mem_size, i;
79 struct cpu_core_map *map;
82 /* Check input arguments */
83 if ((n_max_sockets == 0) ||
84 (n_max_cores_per_socket == 0) ||
85 (n_max_ht_per_core == 0))
88 /* Memory allocation */
89 map_size = n_max_sockets * n_max_cores_per_socket * n_max_ht_per_core;
90 map_mem_size = sizeof(struct cpu_core_map) + map_size * sizeof(int);
91 map = (struct cpu_core_map *) malloc(map_mem_size);
96 map->n_max_sockets = n_max_sockets;
97 map->n_max_cores_per_socket = n_max_cores_per_socket;
98 map->n_max_ht_per_core = n_max_ht_per_core;
100 map->n_cores_per_socket = 0;
101 map->n_ht_per_core = 0;
103 for (i = 0; i < map_size; i++)
106 status = (eal_initialized) ?
107 cpu_core_map_compute_eal(map) :
108 cpu_core_map_compute_linux(map);
115 status = cpu_core_map_compute_and_check(map);
125 cpu_core_map_compute_eal(struct cpu_core_map *map)
127 uint32_t socket_id, core_id, ht_id;
130 for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) {
131 uint32_t n_detected, core_id_contig;
135 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
136 struct lcore_config *p = &lcore_config[lcore_id];
138 if ((p->detected) && (p->socket_id == socket_id))
144 for (core_id = 0; n_detected ; core_id++) {
148 lcore_id < RTE_MAX_LCORE;
150 struct lcore_config *p =
151 &lcore_config[lcore_id];
154 (p->socket_id == socket_id) &&
155 (p->core_id == core_id)) {
156 uint32_t pos = cpu_core_map_pos(map,
161 map->map[pos] = lcore_id;
169 if (core_id_contig ==
170 map->n_max_cores_per_socket)
180 cpu_core_map_compute_and_check(struct cpu_core_map *map)
182 uint32_t socket_id, core_id, ht_id;
184 /* Compute n_ht_per_core, n_cores_per_socket, n_sockets */
185 for (ht_id = 0; ht_id < map->n_max_ht_per_core; ht_id++) {
186 if (map->map[ht_id] == -1)
189 map->n_ht_per_core++;
192 if (map->n_ht_per_core == 0)
195 for (core_id = 0; core_id < map->n_max_cores_per_socket; core_id++) {
196 uint32_t pos = core_id * map->n_max_ht_per_core;
198 if (map->map[pos] == -1)
201 map->n_cores_per_socket++;
204 if (map->n_cores_per_socket == 0)
207 for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) {
208 uint32_t pos = socket_id * map->n_max_cores_per_socket *
209 map->n_max_ht_per_core;
211 if (map->map[pos] == -1)
217 if (map->n_sockets == 0)
220 /* Check that each socket has exactly the same number of cores
221 and that each core has exactly the same number of hyper-threads */
222 for (socket_id = 0; socket_id < map->n_sockets; socket_id++) {
223 for (core_id = 0; core_id < map->n_cores_per_socket; core_id++)
225 ht_id < map->n_max_ht_per_core;
227 uint32_t pos = (socket_id *
228 map->n_max_cores_per_socket + core_id) *
229 map->n_max_ht_per_core + ht_id;
231 if (((ht_id < map->n_ht_per_core) &&
232 (map->map[pos] == -1)) ||
233 ((ht_id >= map->n_ht_per_core) &&
234 (map->map[pos] != -1)))
238 for ( ; core_id < map->n_max_cores_per_socket; core_id++)
240 ht_id < map->n_max_ht_per_core;
242 uint32_t pos = cpu_core_map_pos(map,
247 if (map->map[pos] != -1)
255 #define FILE_LINUX_CPU_N_LCORES \
256 "/sys/devices/system/cpu/present"
259 cpu_core_map_get_n_lcores_linux(void)
261 char buffer[64], *string;
264 fd = fopen(FILE_LINUX_CPU_N_LCORES, "r");
268 if (fgets(buffer, sizeof(buffer), fd) == NULL) {
275 string = index(buffer, '-');
279 return atoi(++string) + 1;
282 #define FILE_LINUX_CPU_CORE_ID \
283 "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_id"
286 cpu_core_map_get_core_id_linux(int lcore_id)
292 snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_CORE_ID, lcore_id);
293 fd = fopen(buffer, "r");
297 if (fgets(buffer, sizeof(buffer), fd) == NULL) {
304 core_id = atoi(buffer);
308 #define FILE_LINUX_CPU_SOCKET_ID \
309 "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/physical_package_id"
312 cpu_core_map_get_socket_id_linux(int lcore_id)
318 snprintf(buffer, sizeof(buffer), FILE_LINUX_CPU_SOCKET_ID, lcore_id);
319 fd = fopen(buffer, "r");
323 if (fgets(buffer, sizeof(buffer), fd) == NULL) {
330 socket_id = atoi(buffer);
335 cpu_core_map_compute_linux(struct cpu_core_map *map)
337 uint32_t socket_id, core_id, ht_id;
340 n_lcores = cpu_core_map_get_n_lcores_linux();
345 for (socket_id = 0; socket_id < map->n_max_sockets; socket_id++) {
346 uint32_t n_detected, core_id_contig;
350 for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) {
351 int lcore_socket_id =
352 cpu_core_map_get_socket_id_linux(lcore_id);
354 if (lcore_socket_id < 0)
357 if (((uint32_t) lcore_socket_id) == socket_id)
363 for (core_id = 0; n_detected ; core_id++) {
366 for (lcore_id = 0; lcore_id < n_lcores; lcore_id++) {
367 int lcore_socket_id =
368 cpu_core_map_get_socket_id_linux(
371 if (lcore_socket_id < 0)
375 cpu_core_map_get_core_id_linux(
378 if (lcore_core_id < 0)
381 if (((uint32_t) lcore_socket_id == socket_id) &&
382 ((uint32_t) lcore_core_id == core_id)) {
383 uint32_t pos = cpu_core_map_pos(map,
388 map->map[pos] = lcore_id;
396 if (core_id_contig ==
397 map->n_max_cores_per_socket)
407 cpu_core_map_print(struct cpu_core_map *map)
409 uint32_t socket_id, core_id, ht_id;
414 for (socket_id = 0; socket_id < map->n_sockets; socket_id++) {
415 printf("Socket %" PRIu32 ":\n", socket_id);
418 core_id < map->n_cores_per_socket;
420 printf("[%" PRIu32 "] = [", core_id);
422 for (ht_id = 0; ht_id < map->n_ht_per_core; ht_id++) {
423 int lcore_id = cpu_core_map_get_lcore_id(map,
428 uint32_t core_id_noncontig =
429 cpu_core_map_get_core_id_linux(
432 printf(" %" PRId32 " (%" PRIu32 ") ",
443 cpu_core_map_get_n_sockets(struct cpu_core_map *map)
448 return map->n_sockets;
452 cpu_core_map_get_n_cores_per_socket(struct cpu_core_map *map)
457 return map->n_cores_per_socket;
461 cpu_core_map_get_n_ht_per_core(struct cpu_core_map *map)
466 return map->n_ht_per_core;
470 cpu_core_map_get_lcore_id(struct cpu_core_map *map,
478 (socket_id >= map->n_sockets) ||
479 (core_id >= map->n_cores_per_socket) ||
480 (ht_id >= map->n_ht_per_core))
483 pos = cpu_core_map_pos(map, socket_id, core_id, ht_id);
485 return map->map[pos];
489 cpu_core_map_free(struct cpu_core_map *map)