Browse Source

init: Make entry init-function less and introduce service objects

Since the addition of deinit operation in device, init and deinit have
been within each device, rendering their init entry's init function
useless.

In order to save ROM space, let's remove the init function from
init entry altogether, and introduce a new object called "service"
which owns an init function to go along with SYS_INIT/SYS_INIT_NAMED.

Signed-off-by: Tomasz Bursztyka <tobu@bang-olufsen.dk>
pull/92309/head
Tomasz Bursztyka 2 months ago committed by Benjamin Cabé
parent
commit
175da6bdb0
  1. 1
      include/zephyr/device.h
  2. 20
      include/zephyr/init.h
  3. 2
      include/zephyr/linker/common-rom/common-rom-kernel-devices.ld
  4. 92
      include/zephyr/service.h
  5. 26
      kernel/init.c
  6. 2
      subsys/net/lib/sockets/sockets_service.c

1
include/zephyr/device.h

@ -1263,7 +1263,6 @@ device_get_dt_nodelabels(const struct device *dev) @@ -1263,7 +1263,6 @@ device_get_dt_nodelabels(const struct device *dev)
static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \
level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
.init_fn = NULL, \
.dev = (const struct device *)&DEVICE_NAME_GET(dev_id), \
}

20
include/zephyr/init.h

@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
#include <zephyr/sys/util.h>
#include <zephyr/toolchain.h>
#include <zephyr/service.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -65,15 +67,14 @@ struct device; @@ -65,15 +67,14 @@ struct device;
*/
struct init_entry {
/**
* If the init function belongs to a SYS_INIT, this field stored the
* initialization function, otherwise it is set to NULL.
*/
int (*init_fn)(void);
/**
* If the init entry belongs to a device, this fields stores a
* reference to it, otherwise it is set to NULL.
* An init entry can be about a device or a service, _init_object
* will be used to differentiate depending on relative sections.
*/
union {
const void *_init_object;
const struct device *dev;
const struct service *srv;
};
};
/** @cond INTERNAL_HIDDEN */
@ -164,9 +165,12 @@ struct init_entry { @@ -164,9 +165,12 @@ struct init_entry {
* @see SYS_INIT()
*/
#define SYS_INIT_NAMED(name, init_fn_, level, prio) \
Z_SERVICE_DEFINE(name, init_fn_, level, prio); \
static const Z_DECL_ALIGN(struct init_entry) \
Z_INIT_ENTRY_SECTION(level, prio, 0) __used __noasan \
Z_INIT_ENTRY_NAME(name) = {.init_fn = (init_fn_), .dev = NULL} \
Z_INIT_ENTRY_NAME(name) = { \
.srv = (const struct service *)&Z_SERVICE_NAME_GET(name) \
}
/** @} */

2
include/zephyr/linker/common-rom/common-rom-kernel-devices.ld

@ -22,6 +22,8 @@ @@ -22,6 +22,8 @@
ITERABLE_SECTION_ROM_NUMERIC(device, Z_LINK_ITERABLE_SUBALIGN)
ITERABLE_SECTION_ROM_NUMERIC(service, Z_LINK_ITERABLE_SUBALIGN)
#if defined(CONFIG_GEN_SW_ISR_TABLE) && defined(CONFIG_SHARED_INTERRUPTS)
/* since z_shared_isr() is not referenced anywhere when
* zephyr_pre0.elf is built, the linker will end up dropping it.

92
include/zephyr/service.h

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
/*
* Copyright (c) 2024 Tomasz Bursztyka.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_SERVICE_H_
#define ZEPHYR_INCLUDE_SERVICE_H_
#include <zephyr/sys/iterable_sections.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup service System service
* @ingroup os_services
*
* A system service is a one-shot initialized software component, instantiated
* via SYS_INIT() or SYS_INIT_NAMED(). It does not provide any public API.
*
* @{
*/
/**
* @brief Structure to store service instance
*
* This will be defined through SYS_INIT/SYS_INIT_NAMED
*/
struct service {
/**
* Initialization function
*/
int (*init)(void);
};
/** @cond INTERNAL_HIDDEN */
/**
* @brief Expands to the name of a global service object
*
* @param name Service name.
*
* @return The full name of the service object defined by the service
* definition macro.
*/
#define Z_SERVICE_NAME_GET(name) _CONCAT(__service_, name)
/**
* @brief Initializer for @ref service
*
* @param init_fn Initialization function (mandatory).
*/
#define Z_SERVICE_INIT(init_fn) \
{ \
.init = (init_fn) \
}
/**
* @brief Service section name (used for sorting purposes).
*
* @param level Initialization level.
* @param prio Initialization priority.
*/
#define Z_SERVICE_SECTION_NAME(level, prio) \
_CONCAT(INIT_LEVEL_ORD(level), _##prio)
/**
* @brief Define a @ref service
*
* @param name Service name.
* @param init_fn Initialization function.
* @param level Initialization level.
* @param prio Initialization priority.
*/
#define Z_SERVICE_DEFINE(name, init_fn, level, prio) \
static const \
STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \
service, service, \
Z_SERVICE_SECTION_NAME(level, prio), \
Z_SERVICE_NAME_GET(name)) = Z_SERVICE_INIT(init_fn)
/** @endcond */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_SERVICE_H_ */

26
kernel/init.c

@ -136,6 +136,9 @@ enum init_level { @@ -136,6 +136,9 @@ enum init_level {
extern const struct init_entry __init_SMP_start[];
#endif /* CONFIG_SMP */
TYPE_SECTION_START_EXTERN(struct service, service);
TYPE_SECTION_END_EXTERN(struct service, service);
/*
* storage space for the interrupt stack
*
@ -337,6 +340,12 @@ static int do_device_init(const struct device *dev) @@ -337,6 +340,12 @@ static int do_device_init(const struct device *dev)
return rc;
}
static inline bool is_entry_about_service(const void *obj)
{
return (obj >= (void *)_service_list_start &&
obj < (void *)_service_list_end);
}
/**
* @brief Execute all the init entry initialization functions at a given level
*
@ -365,17 +374,26 @@ static void z_sys_init_run_level(enum init_level level) @@ -365,17 +374,26 @@ static void z_sys_init_run_level(enum init_level level)
const struct init_entry *entry;
for (entry = levels[level]; entry < levels[level+1]; entry++) {
const struct device *dev = entry->dev;
int result = 0;
if (unlikely(entry->_init_object == NULL)) {
continue;
}
sys_trace_sys_init_enter(entry, level);
if (dev != NULL) {
if (is_entry_about_service(entry->_init_object)) {
const struct service *srv = entry->srv;
result = srv->init();
} else {
const struct device *dev = entry->dev;
if ((dev->flags & DEVICE_FLAG_INIT_DEFERRED) == 0U) {
result = do_device_init(dev);
}
} else {
result = entry->init_fn();
}
sys_trace_sys_init_exit(entry, level, result);
}
}

2
subsys/net/lib/sockets/sockets_service.c

@ -28,7 +28,7 @@ static K_CONDVAR_DEFINE(wait_start); @@ -28,7 +28,7 @@ static K_CONDVAR_DEFINE(wait_start);
STRUCT_SECTION_START_EXTERN(net_socket_service_desc);
STRUCT_SECTION_END_EXTERN(net_socket_service_desc);
static struct service {
static struct service_context {
struct zsock_pollfd events[CONFIG_ZVFS_POLL_MAX];
int count;
} ctx;

Loading…
Cancel
Save