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/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..da68aaf300 --- /dev/null +++ b/lib/init/rte_init.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2024 Red Hat, Inc. + */ + +#include +#include + +#include +#include + +static bool init_called; + +static RTE_TAILQ_HEAD(, rte_init) init_list = TAILQ_HEAD_INITIALIZER(init_list); +struct rte_init { + RTE_TAILQ_ENTRY(rte_init) next; + unsigned int priority; + const char *func; + void (*init)(void); +}; + +void +rte_init_register(const char *func, void (*init)(void), unsigned int priority) +{ + struct rte_init *p; + struct rte_init *i; + + /* + * This code has been invoked after rte_eal_init() (common case is with drivers loaded + * as shared libraries). + */ + if (init_called) { + init(); + return; + } + + i = malloc(sizeof(*i)); + if (i == NULL) + return; + + i->priority = priority; + i->func = func; + i->init = init; + + 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->init(); +} diff --git a/lib/init/rte_init.h b/lib/init/rte_init.h index 3ebb7339ac..87351178ab 100644 --- a/lib/init/rte_init.h +++ b/lib/init/rte_init.h @@ -5,6 +5,17 @@ #ifndef RTE_INIT_H #define RTE_INIT_H +#include + +#include + +void +rte_init_register(const char *func, void (*init)(void), unsigned int prio); + +__rte_internal +void +eal_init_early(void); + #define RTE_PRIORITY_LOG 101 #define RTE_PRIORITY_BUS 110 #define RTE_PRIORITY_CLASS 120 @@ -25,7 +36,12 @@ #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 void __attribute__((constructor(RTE_PRIO(prio)), used)) init_ ## func(void) \ +{ \ + rte_init_register(#func, func, RTE_PRIO(prio)); \ +} \ +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; +};