diff --git a/lib/eal/freebsd/eal.c b/lib/eal/freebsd/eal.c index a96bbf5836..3d224b47df 100644 --- a/lib/eal/freebsd/eal.c +++ b/lib/eal/freebsd/eal.c @@ -548,6 +548,8 @@ rte_eal_init(int argc, char **argv) bool has_phys_addr; enum rte_iova_mode iova_mode; + eal_init_early(); + /* setup log as early as possible */ if (eal_parse_log_options(argc, argv) < 0) { rte_eal_init_alert("invalid log arguments."); diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c index a6220524a4..afcbba4397 100644 --- a/lib/eal/linux/eal.c +++ b/lib/eal/linux/eal.c @@ -927,6 +927,8 @@ rte_eal_init(int argc, char **argv) struct internal_config *internal_conf = eal_get_internal_configuration(); + eal_init_early(); + /* setup log as early as possible */ if (eal_parse_log_options(argc, argv) < 0) { rte_eal_init_alert("invalid log arguments."); diff --git a/lib/eal/windows/eal.c b/lib/eal/windows/eal.c index 5cdc053a02..de1a984028 100644 --- a/lib/eal/windows/eal.c +++ b/lib/eal/windows/eal.c @@ -251,6 +251,8 @@ rte_eal_init(int argc, char **argv) char cpuset[RTE_CPU_AFFINITY_STR_LEN]; char thread_name[RTE_THREAD_NAME_SIZE]; + eal_init_early(); + /* setup log as early as possible */ if (eal_parse_log_options(argc, argv) < 0) { rte_eal_init_alert("invalid log arguments."); diff --git a/lib/init/meson.build b/lib/init/meson.build index a6c1ade098..e503dd7294 100644 --- a/lib/init/meson.build +++ b/lib/init/meson.build @@ -1,4 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) 2024 Red Hat, Inc. +includes += global_inc +sources = files('rte_init.c') headers = files('rte_init.h') diff --git a/lib/init/rte_init.c b/lib/init/rte_init.c new file mode 100644 index 0000000000..0d85f2508d --- /dev/null +++ b/lib/init/rte_init.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2024 Red Hat, Inc. + */ + +#include +#include + +#include + +#include +#include + +static bool init_called; + +static TAILQ_HEAD(, rte_init) init_list = TAILQ_HEAD_INITIALIZER(init_list); + +void +rte_init_register(struct rte_init *i) +{ + struct rte_init *p; + + /* + * This code has been invoked after rte_eal_init() (common case is with drivers loaded + * as shared libraries). + */ + if (init_called) { + i->callback(); + return; + } + + TAILQ_FOREACH(p, &init_list, next) { + if (i->priority >= p->priority) + continue; + TAILQ_INSERT_BEFORE(p, i, next); + return; + } + + TAILQ_INSERT_TAIL(&init_list, i, next); +} + +void +eal_init_early(void) +{ + struct rte_init *i; + + init_called = true; + + TAILQ_FOREACH(i, &init_list, next) + i->callback(); +} diff --git a/lib/init/rte_init.h b/lib/init/rte_init.h index 3ebb7339ac..0e271730da 100644 --- a/lib/init/rte_init.h +++ b/lib/init/rte_init.h @@ -5,6 +5,24 @@ #ifndef RTE_INIT_H #define RTE_INIT_H +#include + +#include + +#include + +struct rte_init { + TAILQ_ENTRY(rte_init) next; + unsigned int priority; + void (*callback)(void); +}; +void +rte_init_register(struct rte_init *i); + +__rte_internal +void +eal_init_early(void); + #define RTE_PRIORITY_LOG 101 #define RTE_PRIORITY_BUS 110 #define RTE_PRIORITY_CLASS 120 @@ -25,7 +43,16 @@ #ifndef RTE_INIT_PRIO /* Allow to override from EAL */ #ifndef RTE_TOOLCHAIN_MSVC #define RTE_INIT_PRIO(func, prio) \ -static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void) +static void func(void); \ +static struct rte_init init_obj_ ## func; \ +static void __attribute__((constructor(RTE_PRIO(prio)), used)) init_ ## func(void) \ +{ \ + struct rte_init *i = &init_obj_ ## func; \ + i->callback = func; \ + i->priority = RTE_PRIO(prio); \ + rte_init_register(i); \ +} \ +static void func(void) #else /* definition from the Microsoft CRT */ typedef int(__cdecl *_PIFV)(void); diff --git a/lib/init/version.map b/lib/init/version.map index 17cc97bda6..de82294019 100644 --- a/lib/init/version.map +++ b/lib/init/version.map @@ -1,3 +1,13 @@ DPDK_25 { + global: + + rte_init_register; + local: *; }; + +INTERNAL { + global: + + eal_init_early; +};