From 6037b5238f6fdb7e586a290b9f93447848f41685 Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Thu, 11 Jul 2024 16:51:21 +0300 Subject: [PATCH] linux-gen: cpu: make possible to read cpu id during every odp_cpu_id() call Add new config file option 'system:cpu_id_static' for selecting whether the implementation reads CPU identifier value from OS during every odp_cpu_id() call or only once during thread initialization (default). If thread(s) may be migrated between cores during the application lifetime this option should be set to 0. Signed-off-by: Matias Elo Reviewed-by: Tuomas Taipale --- config/odp-linux-generic.conf | 10 ++++- .../odp/api/plat/thread_inline_types.h | 1 + .../include/odp/api/plat/thread_inlines.h | 6 ++- .../linux-generic/include/odp_global_data.h | 1 + platform/linux-generic/m4/odp_libconfig.m4 | 2 +- platform/linux-generic/odp_system_info.c | 19 +++++++- platform/linux-generic/odp_thread.c | 45 ++++++++++++------- platform/linux-generic/test/inline-timer.conf | 2 +- platform/linux-generic/test/packet_align.conf | 2 +- platform/linux-generic/test/process-mode.conf | 2 +- platform/linux-generic/test/sched-basic.conf | 2 +- platform/linux-generic/test/stash-custom.conf | 2 +- 12 files changed, 69 insertions(+), 25 deletions(-) diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf index 93997ecb3c..97f270ee07 100644 --- a/config/odp-linux-generic.conf +++ b/config/odp-linux-generic.conf @@ -16,7 +16,7 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.28" +config_file_version = "0.1.29" # System options system: { @@ -38,6 +38,14 @@ system: { # scaling is disabled. cpu_hz_static = 0 + # When enabled (1), implementation reads the CPU identifier values from + # OS only once during ODP initialization. Enabling this option removes + # a system call from odp_cpu_id() implementation. + # + # This option should only be used when ODP threads are not migrated + # during application lifetime. + cpu_id_static = 1 + # Maximum number of ODP threads that can be created. # odp_thread_count_max() returns this value or the build time # maximum ODP_THREAD_COUNT_MAX, whichever is lower. This setting diff --git a/platform/linux-generic/include/odp/api/plat/thread_inline_types.h b/platform/linux-generic/include/odp/api/plat/thread_inline_types.h index e594a37ff4..596cef4a79 100644 --- a/platform/linux-generic/include/odp/api/plat/thread_inline_types.h +++ b/platform/linux-generic/include/odp/api/plat/thread_inline_types.h @@ -17,6 +17,7 @@ extern "C" { typedef struct { odp_log_func_t log_fn; + int (*cpu_id_fn)(void); odp_thread_type_t type; int thr; int cpu; diff --git a/platform/linux-generic/include/odp/api/plat/thread_inlines.h b/platform/linux-generic/include/odp/api/plat/thread_inlines.h index be8ee9725a..ce14d566bb 100644 --- a/platform/linux-generic/include/odp/api/plat/thread_inlines.h +++ b/platform/linux-generic/include/odp/api/plat/thread_inlines.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2018 Linaro Limited + * Copyright (c) 2024 Nokia */ #ifndef ODP_PLAT_THREAD_INLINES_H_ @@ -37,7 +38,10 @@ _ODP_INLINE odp_thread_type_t odp_thread_type(void) _ODP_INLINE int odp_cpu_id(void) { - return _odp_this_thread->cpu; + if (_odp_this_thread->cpu >= 0) + return _odp_this_thread->cpu; + + return _odp_this_thread->cpu_id_fn(); } /** @endcond */ diff --git a/platform/linux-generic/include/odp_global_data.h b/platform/linux-generic/include/odp_global_data.h index e532cf0e7c..51f0f0e224 100644 --- a/platform/linux-generic/include/odp_global_data.h +++ b/platform/linux-generic/include/odp_global_data.h @@ -33,6 +33,7 @@ typedef struct { uint64_t page_size; int cache_line_size; uint8_t cpu_hz_static; + uint8_t cpu_id_static; uint8_t cpu_constant_tsc; odp_cpu_arch_t cpu_arch; odp_cpu_arch_isa_t cpu_isa_sw; diff --git a/platform/linux-generic/m4/odp_libconfig.m4 b/platform/linux-generic/m4/odp_libconfig.m4 index 25ffd87a4e..ac55299486 100644 --- a/platform/linux-generic/m4/odp_libconfig.m4 +++ b/platform/linux-generic/m4/odp_libconfig.m4 @@ -7,7 +7,7 @@ ########################################################################## m4_define([_odp_config_version_generation], [0]) m4_define([_odp_config_version_major], [1]) -m4_define([_odp_config_version_minor], [28]) +m4_define([_odp_config_version_minor], [29]) m4_define([_odp_config_version], [_odp_config_version_generation._odp_config_version_major._odp_config_version_minor]) diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c index c310684920..9538a79b43 100644 --- a/platform/linux-generic/odp_system_info.c +++ b/platform/linux-generic/odp_system_info.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2013-2018 Linaro Limited - * Copyright (c) 2020-2022 Nokia + * Copyright (c) 2020-2024 Nokia * * Copyright(c) 2010-2014 Intel Corporation * - lib/eal/common/eal_common_string_fns.c @@ -337,6 +337,23 @@ static int read_config_file(void) } odp_global_ro.system_info.cpu_hz_static = !!val; + str = "system.cpu_id_static"; + if (!_odp_libconfig_lookup_int(str, &val)) { + _ODP_ERR("Config option '%s' not found.\n", str); + return -1; + } + odp_global_ro.system_info.cpu_id_static = !!val; + + _ODP_PRINT("System config:\n"); + _ODP_PRINT(" system.cpu_mhz: %" PRIu64 "\n", + odp_global_ro.system_info.default_cpu_hz); + _ODP_PRINT(" system.cpu_mhz_max: %" PRIu64 "\n", + odp_global_ro.system_info.default_cpu_hz_max); + _ODP_PRINT(" system.cpu_hz_static: %" PRIu8 "\n", + odp_global_ro.system_info.cpu_hz_static); + _ODP_PRINT(" system.cpu_id_static: %" PRIu8 "\n\n", + odp_global_ro.system_info.cpu_id_static); + return 0; } diff --git a/platform/linux-generic/odp_thread.c b/platform/linux-generic/odp_thread.c index 34dbb2990f..d66953dc9c 100644 --- a/platform/linux-generic/odp_thread.c +++ b/platform/linux-generic/odp_thread.c @@ -1,28 +1,32 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2013-2018 Linaro Limited - * Copyright (c) 2021 Nokia + * Copyright (c) 2021-2024 Nokia */ #include -#include +#include #include +#include +#include +#include #include #include -#include -#include + +#include + #include #include -#include -#include -#include -#include -#include +#include +#include #include +#include -#include +#include +#include #include #include +#include typedef struct { _odp_thread_state_t thr[ODP_THREAD_COUNT_MAX]; @@ -154,6 +158,17 @@ static int free_id(int thr) return odp_atomic_fetch_dec_u32(&thread_globals->num) - 1; } +static int cpu_id(void) +{ + int cpu = sched_getcpu(); + + if (odp_unlikely(cpu < 0)) { + _ODP_ERR("sched_getcpu() failed: %s\n", strerror(errno)); + return -1; + } + return cpu; +} + int _odp_thread_init_local(odp_thread_type_t type) { int id; @@ -182,15 +197,13 @@ int _odp_thread_init_local(odp_thread_type_t type) return -1; } - cpu = sched_getcpu(); - - if (cpu < 0) { - _ODP_ERR("getcpu failed\n"); + cpu = cpu_id(); + if (cpu < 0) return -1; - } thread_globals->thr[id].thr = id; - thread_globals->thr[id].cpu = cpu; + thread_globals->thr[id].cpu = odp_global_ro.system_info.cpu_id_static ? cpu : -1; + thread_globals->thr[id].cpu_id_fn = cpu_id; thread_globals->thr[id].type = type; _odp_this_thread = &thread_globals->thr[id]; diff --git a/platform/linux-generic/test/inline-timer.conf b/platform/linux-generic/test/inline-timer.conf index fa3b6982fb..b5a82d0d3d 100644 --- a/platform/linux-generic/test/inline-timer.conf +++ b/platform/linux-generic/test/inline-timer.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.28" +config_file_version = "0.1.29" timer: { # Enable inline timer implementation diff --git a/platform/linux-generic/test/packet_align.conf b/platform/linux-generic/test/packet_align.conf index fb14183480..270ccd1b41 100644 --- a/platform/linux-generic/test/packet_align.conf +++ b/platform/linux-generic/test/packet_align.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.28" +config_file_version = "0.1.29" pool: { pkt: { diff --git a/platform/linux-generic/test/process-mode.conf b/platform/linux-generic/test/process-mode.conf index f4c6f7952a..3c44e4872a 100644 --- a/platform/linux-generic/test/process-mode.conf +++ b/platform/linux-generic/test/process-mode.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.28" +config_file_version = "0.1.29" # Shared memory options shm: { diff --git a/platform/linux-generic/test/sched-basic.conf b/platform/linux-generic/test/sched-basic.conf index 8a6d0ac983..8e5653d84d 100644 --- a/platform/linux-generic/test/sched-basic.conf +++ b/platform/linux-generic/test/sched-basic.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.28" +config_file_version = "0.1.29" # Test scheduler with an odd spread value and without dynamic load balance sched_basic: { diff --git a/platform/linux-generic/test/stash-custom.conf b/platform/linux-generic/test/stash-custom.conf index 6a24963035..6f0f77a59a 100644 --- a/platform/linux-generic/test/stash-custom.conf +++ b/platform/linux-generic/test/stash-custom.conf @@ -1,6 +1,6 @@ # Mandatory fields odp_implementation = "linux-generic" -config_file_version = "0.1.28" +config_file_version = "0.1.29" # Test overflow safe stash variant stash: {