Skip to content

Commit 175da6b

Browse files
tbursztykakartben
authored andcommitted
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>
1 parent e4348ad commit 175da6b

File tree

6 files changed

+130
-15
lines changed

6 files changed

+130
-15
lines changed

include/zephyr/device.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,6 @@ device_get_dt_nodelabels(const struct device *dev)
12631263
static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \
12641264
level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \
12651265
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
1266-
.init_fn = NULL, \
12671266
.dev = (const struct device *)&DEVICE_NAME_GET(dev_id), \
12681267
}
12691268

include/zephyr/init.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include <zephyr/sys/util.h>
1414
#include <zephyr/toolchain.h>
1515

16+
#include <zephyr/service.h>
17+
1618
#ifdef __cplusplus
1719
extern "C" {
1820
#endif
@@ -65,15 +67,14 @@ struct device;
6567
*/
6668
struct init_entry {
6769
/**
68-
* If the init function belongs to a SYS_INIT, this field stored the
69-
* initialization function, otherwise it is set to NULL.
70-
*/
71-
int (*init_fn)(void);
72-
/**
73-
* If the init entry belongs to a device, this fields stores a
74-
* reference to it, otherwise it is set to NULL.
70+
* An init entry can be about a device or a service, _init_object
71+
* will be used to differentiate depending on relative sections.
7572
*/
76-
const struct device *dev;
73+
union {
74+
const void *_init_object;
75+
const struct device *dev;
76+
const struct service *srv;
77+
};
7778
};
7879

7980
/** @cond INTERNAL_HIDDEN */
@@ -164,9 +165,12 @@ struct init_entry {
164165
* @see SYS_INIT()
165166
*/
166167
#define SYS_INIT_NAMED(name, init_fn_, level, prio) \
168+
Z_SERVICE_DEFINE(name, init_fn_, level, prio); \
167169
static const Z_DECL_ALIGN(struct init_entry) \
168170
Z_INIT_ENTRY_SECTION(level, prio, 0) __used __noasan \
169-
Z_INIT_ENTRY_NAME(name) = {.init_fn = (init_fn_), .dev = NULL} \
171+
Z_INIT_ENTRY_NAME(name) = { \
172+
.srv = (const struct service *)&Z_SERVICE_NAME_GET(name) \
173+
}
170174

171175
/** @} */
172176

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
ITERABLE_SECTION_ROM_NUMERIC(device, Z_LINK_ITERABLE_SUBALIGN)
2424

25+
ITERABLE_SECTION_ROM_NUMERIC(service, Z_LINK_ITERABLE_SUBALIGN)
26+
2527
#if defined(CONFIG_GEN_SW_ISR_TABLE) && defined(CONFIG_SHARED_INTERRUPTS)
2628
/* since z_shared_isr() is not referenced anywhere when
2729
* zephyr_pre0.elf is built, the linker will end up dropping it.

include/zephyr/service.h

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (c) 2024 Tomasz Bursztyka.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_SERVICE_H_
8+
#define ZEPHYR_INCLUDE_SERVICE_H_
9+
10+
#include <zephyr/sys/iterable_sections.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
/**
17+
* @defgroup service System service
18+
* @ingroup os_services
19+
*
20+
* A system service is a one-shot initialized software component, instantiated
21+
* via SYS_INIT() or SYS_INIT_NAMED(). It does not provide any public API.
22+
*
23+
* @{
24+
*/
25+
26+
/**
27+
* @brief Structure to store service instance
28+
*
29+
* This will be defined through SYS_INIT/SYS_INIT_NAMED
30+
*/
31+
struct service {
32+
/**
33+
* Initialization function
34+
*/
35+
int (*init)(void);
36+
};
37+
38+
/** @cond INTERNAL_HIDDEN */
39+
40+
/**
41+
* @brief Expands to the name of a global service object
42+
*
43+
* @param name Service name.
44+
*
45+
* @return The full name of the service object defined by the service
46+
* definition macro.
47+
*/
48+
#define Z_SERVICE_NAME_GET(name) _CONCAT(__service_, name)
49+
50+
/**
51+
* @brief Initializer for @ref service
52+
*
53+
* @param init_fn Initialization function (mandatory).
54+
*/
55+
#define Z_SERVICE_INIT(init_fn) \
56+
{ \
57+
.init = (init_fn) \
58+
}
59+
60+
/**
61+
* @brief Service section name (used for sorting purposes).
62+
*
63+
* @param level Initialization level.
64+
* @param prio Initialization priority.
65+
*/
66+
#define Z_SERVICE_SECTION_NAME(level, prio) \
67+
_CONCAT(INIT_LEVEL_ORD(level), _##prio)
68+
69+
/**
70+
* @brief Define a @ref service
71+
*
72+
* @param name Service name.
73+
* @param init_fn Initialization function.
74+
* @param level Initialization level.
75+
* @param prio Initialization priority.
76+
*/
77+
#define Z_SERVICE_DEFINE(name, init_fn, level, prio) \
78+
static const \
79+
STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \
80+
service, service, \
81+
Z_SERVICE_SECTION_NAME(level, prio), \
82+
Z_SERVICE_NAME_GET(name)) = Z_SERVICE_INIT(init_fn)
83+
84+
/** @endcond */
85+
86+
/** @} */
87+
88+
#ifdef __cplusplus
89+
}
90+
#endif
91+
92+
#endif /* ZEPHYR_INCLUDE_SERVICE_H_ */

kernel/init.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ enum init_level {
136136
extern const struct init_entry __init_SMP_start[];
137137
#endif /* CONFIG_SMP */
138138

139+
TYPE_SECTION_START_EXTERN(struct service, service);
140+
TYPE_SECTION_END_EXTERN(struct service, service);
141+
139142
/*
140143
* storage space for the interrupt stack
141144
*
@@ -337,6 +340,12 @@ static int do_device_init(const struct device *dev)
337340
return rc;
338341
}
339342

343+
static inline bool is_entry_about_service(const void *obj)
344+
{
345+
return (obj >= (void *)_service_list_start &&
346+
obj < (void *)_service_list_end);
347+
}
348+
340349
/**
341350
* @brief Execute all the init entry initialization functions at a given level
342351
*
@@ -365,17 +374,26 @@ static void z_sys_init_run_level(enum init_level level)
365374
const struct init_entry *entry;
366375

367376
for (entry = levels[level]; entry < levels[level+1]; entry++) {
368-
const struct device *dev = entry->dev;
369377
int result = 0;
370378

379+
if (unlikely(entry->_init_object == NULL)) {
380+
continue;
381+
}
382+
371383
sys_trace_sys_init_enter(entry, level);
372-
if (dev != NULL) {
384+
385+
if (is_entry_about_service(entry->_init_object)) {
386+
const struct service *srv = entry->srv;
387+
388+
result = srv->init();
389+
} else {
390+
const struct device *dev = entry->dev;
391+
373392
if ((dev->flags & DEVICE_FLAG_INIT_DEFERRED) == 0U) {
374393
result = do_device_init(dev);
375394
}
376-
} else {
377-
result = entry->init_fn();
378395
}
396+
379397
sys_trace_sys_init_exit(entry, level, result);
380398
}
381399
}

subsys/net/lib/sockets/sockets_service.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static K_CONDVAR_DEFINE(wait_start);
2828
STRUCT_SECTION_START_EXTERN(net_socket_service_desc);
2929
STRUCT_SECTION_END_EXTERN(net_socket_service_desc);
3030

31-
static struct service {
31+
static struct service_context {
3232
struct zsock_pollfd events[CONFIG_ZVFS_POLL_MAX];
3333
int count;
3434
} ctx;

0 commit comments

Comments
 (0)