Skip to content

Commit 5d04385

Browse files
committed
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 <[email protected]>
1 parent 1938403 commit 5d04385

File tree

5 files changed

+135
-14
lines changed

5 files changed

+135
-14
lines changed

include/zephyr/device.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1241,7 +1241,6 @@ device_get_dt_nodelabels(const struct device *dev)
12411241
static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \
12421242
level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \
12431243
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
1244-
.init_fn = NULL, \
12451244
.dev = (const struct device *)&DEVICE_NAME_GET(dev_id), \
12461245
}
12471246

include/zephyr/init.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ extern "C" {
4848
*/
4949

5050
struct device;
51+
struct service;
5152

5253
/**
5354
* @brief Structure to store initialization entry information.
@@ -65,15 +66,14 @@ struct device;
6566
*/
6667
struct init_entry {
6768
/**
68-
* If the init function belongs to a SYS_INIT, this field stored the
69-
* initialization function, otherwise it is set to NULL.
69+
* An init entry can be about a device or a service, _init_object
70+
* will be used to differentiate depending on relative sections.
7071
*/
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.
75-
*/
76-
const struct device *dev;
72+
union {
73+
const void *_init_object;
74+
const struct device *dev;
75+
const struct service *srv;
76+
};
7777
};
7878

7979
/** @cond INTERNAL_HIDDEN */
@@ -131,6 +131,8 @@ struct init_entry {
131131
(COND_CODE_1(Z_INIT_SMP_##level, (Z_INIT_ORD_SMP), \
132132
(ZERO_OR_COMPILE_ERROR(0)))))))))))))
133133

134+
#include <zephyr/service.h>
135+
134136
/**
135137
* @brief Register an initialization function.
136138
*
@@ -164,9 +166,12 @@ struct init_entry {
164166
* @see SYS_INIT()
165167
*/
166168
#define SYS_INIT_NAMED(name, init_fn_, level, prio) \
169+
Z_SERVICE_DEFINE(name, init_fn_, level, prio); \
167170
static const Z_DECL_ALIGN(struct init_entry) \
168171
Z_INIT_ENTRY_SECTION(level, prio, 0) __used __noasan \
169-
Z_INIT_ENTRY_NAME(name) = {.init_fn = (init_fn_), .dev = NULL} \
172+
Z_INIT_ENTRY_NAME(name) = { \
173+
.srv = (const struct service *)&Z_SERVICE_NAME_GET(name) \
174+
}
170175

171176
/** @} */
172177

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

0 commit comments

Comments
 (0)