Populate the platform info structure with details of all the cores on the system.
Signed-off-by: Bruce Richardson <[email protected]> --- lib/eal/common/eal_common_lcore.c | 19 ++++++++++++++ lib/eal/common/eal_internal_cfg.h | 16 ++++++++++-- lib/eal/common/eal_private.h | 8 ++++++ lib/eal/freebsd/eal_lcore.c | 16 ++++++++---- lib/eal/linux/eal_lcore.c | 43 +++++++++++++++++++++++++++++++ lib/eal/windows/eal_lcore.c | 6 +++++ 6 files changed, 101 insertions(+), 7 deletions(-) diff --git a/lib/eal/common/eal_common_lcore.c b/lib/eal/common/eal_common_lcore.c index b5f59a6380..a5f5c99af9 100644 --- a/lib/eal/common/eal_common_lcore.c +++ b/lib/eal/common/eal_common_lcore.c @@ -153,6 +153,7 @@ rte_eal_cpu_init(void) { /* pointer to global configuration */ struct rte_config *config = rte_eal_get_configuration(); + struct eal_platform_info *platform_info = eal_get_platform_info(); unsigned lcore_id; unsigned count = 0; unsigned int socket_id, prev_socket_id; @@ -162,6 +163,24 @@ rte_eal_cpu_init(void) int lcore_to_socket_id[RTE_MAX_LCORE] = {0}; #endif + /* allocate cpu_info for all CPUs visible to the OS */ + platform_info->cpu_count = eal_cpu_max(); + platform_info->cpu_info = calloc(platform_info->cpu_count, + sizeof(*platform_info->cpu_info)); + if (platform_info->cpu_info == NULL) { + EAL_LOG(ERR, "Cannot allocate cpu_info array"); + return -1; + } + + /* populate cpu_info with hardware topology for all detected CPUs */ + for (size_t cpu_id = 0; cpu_id < platform_info->cpu_count; cpu_id++) { + if (eal_cpu_detected(cpu_id) == 0) + continue; + platform_info->cpu_info[cpu_id].detected = true; + platform_info->cpu_info[cpu_id].numa_id = eal_cpu_socket_id(cpu_id); + platform_info->cpu_info[cpu_id].core_id = eal_cpu_core_id(cpu_id); + } + /* * Parse the maximum set of logical cores, detect the subset of running * ones and enable them by default. diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h index e63f84fe78..a4243cbfa5 100644 --- a/lib/eal/common/eal_internal_cfg.h +++ b/lib/eal/common/eal_internal_cfg.h @@ -94,10 +94,22 @@ struct eal_user_cfg { }; /** - * Discovered information about cores, memory, etc. on the system. - * Immutable after initialization, so no need for atomic types or locks. + * Hardware facts about a single physical CPU, populated during CPU discovery. + * Indexed by physical CPU ID (not DPDK lcore ID). + */ +struct eal_cpu_info { + bool detected; /**< true if this CPU ID is valid and visible to the OS */ + unsigned int numa_id; /**< NUMA node this CPU belongs to */ + unsigned int core_id; /**< physical core number on its NUMA node */ +}; + +/** + * Discovered information about the system hardware. + * Immutable after discovery. */ struct eal_platform_info { + size_t cpu_count; /**< number of entries in cpu_info[] */ + struct eal_cpu_info *cpu_info; /**< per-physical-CPU hardware facts */ uint8_t num_hugepage_sizes; /**< how many sizes on this system */ struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES]; }; diff --git a/lib/eal/common/eal_private.h b/lib/eal/common/eal_private.h index f31254dac7..c4a7a35cd9 100644 --- a/lib/eal/common/eal_private.h +++ b/lib/eal/common/eal_private.h @@ -404,6 +404,14 @@ unsigned eal_cpu_core_id(unsigned lcore_id); */ int eal_cpu_detected(unsigned lcore_id); +/** + * Get the number of CPU IDs to allocate for platform CPU info. + * Returns max_cpu_id + 1: all valid CPU IDs are in [0, eal_cpu_max()). + * + * This function is private to the EAL. + */ +size_t eal_cpu_max(void); + /** * Set TSC frequency from precise value or estimation * diff --git a/lib/eal/freebsd/eal_lcore.c b/lib/eal/freebsd/eal_lcore.c index 1d3d1b67b9..9d7027ceac 100644 --- a/lib/eal/freebsd/eal_lcore.c +++ b/lib/eal/freebsd/eal_lcore.c @@ -2,7 +2,10 @@ * Copyright(c) 2010-2014 Intel Corporation */ +#include <sched.h> +#include <errno.h> #include <unistd.h> +#include <string.h> #include <sys/sysctl.h> #include <rte_log.h> @@ -21,18 +24,21 @@ eal_cpu_core_id(__rte_unused unsigned lcore_id) return 0; } -static int -eal_get_ncpus(void) +size_t +eal_cpu_max(void) { static int ncpu = -1; int mib[2] = {CTL_HW, HW_NCPU}; size_t len = sizeof(ncpu); if (ncpu < 0) { - sysctl(mib, 2, &ncpu, &len, NULL, 0); + if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) { + EAL_LOG(ERR, "sysctl failed to get number of CPUs: %s", strerror(errno)); + return CPU_SETSIZE; /* fallback to CPU_SETSIZE */ + } EAL_LOG(INFO, "Sysctl reports %d cpus", ncpu); } - return ncpu; + return (size_t)ncpu; } unsigned @@ -47,6 +53,6 @@ eal_cpu_socket_id(__rte_unused unsigned cpu_id) int eal_cpu_detected(unsigned lcore_id) { - const unsigned ncpus = eal_get_ncpus(); + const unsigned int ncpus = eal_cpu_max(); return lcore_id < ncpus; } diff --git a/lib/eal/linux/eal_lcore.c b/lib/eal/linux/eal_lcore.c index 29b36dd610..b8b2196ab6 100644 --- a/lib/eal/linux/eal_lcore.c +++ b/lib/eal/linux/eal_lcore.c @@ -4,7 +4,10 @@ #include <unistd.h> #include <limits.h> +#include <stdio.h> +#include <string.h> +#include <rte_argparse.h> #include <rte_log.h> #include "eal_private.h" @@ -12,9 +15,31 @@ #include "eal_thread.h" #define SYS_CPU_DIR "/sys/devices/system/cpu/cpu%u" +#define SYS_CPU_POSSIBLE_PATH "/sys/devices/system/cpu/possible" #define CORE_ID_FILE "topology/core_id" #define NUMA_NODE_PATH "/sys/devices/system/node" +static int +eal_cpu_possible(rte_cpuset_t *cpuset) +{ + char cpu_list[BUFSIZ]; + FILE *f; + + f = fopen(SYS_CPU_POSSIBLE_PATH, "r"); + if (f == NULL) + return -1; + if (fgets(cpu_list, sizeof(cpu_list), f) == NULL || + strchr(cpu_list, '\n') == NULL) { + fclose(f); + return -1; + } + fclose(f); + cpu_list[strcspn(cpu_list, "\n")] = '\0'; + + return rte_argparse_parse_type(cpu_list, + RTE_ARGPARSE_VALUE_TYPE_CORELIST, cpuset); +} + /* Check if a cpu is present by the presence of the cpu information for it */ int eal_cpu_detected(unsigned lcore_id) @@ -72,3 +97,21 @@ eal_cpu_core_id(unsigned lcore_id) "for lcore %u - assuming core 0", SYS_CPU_DIR, lcore_id); return 0; } + +size_t +eal_cpu_max(void) +{ + rte_cpuset_t possible_cpus; + int cpu_id; + + if (eal_cpu_possible(&possible_cpus) == 0) { + for (cpu_id = CPU_SETSIZE - 1; cpu_id >= 0; cpu_id--) { + if (CPU_ISSET(cpu_id, &possible_cpus)) + return cpu_id + 1; + } + } + + EAL_LOG(WARNING, "Cannot read possible CPU IDs from %s, falling back to CPU_SETSIZE", + SYS_CPU_POSSIBLE_PATH); + return CPU_SETSIZE; +} diff --git a/lib/eal/windows/eal_lcore.c b/lib/eal/windows/eal_lcore.c index d2a2c2d091..2287337530 100644 --- a/lib/eal/windows/eal_lcore.c +++ b/lib/eal/windows/eal_lcore.c @@ -273,6 +273,12 @@ eal_cpu_core_id(unsigned int lcore_id) return cpu_map.lcores[lcore_id].core_id; } +size_t +eal_cpu_max(void) +{ + return (size_t)cpu_map.lcore_count; +} + unsigned int eal_socket_numa_node(unsigned int socket_id) { -- 2.53.0

