Line data Source code
1 0 : /*
2 : * Copyright (C) 2020, Intel Corporation
3 : * Copyright (C) 2023, Nordic Semiconductor ASA
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef INCLUDE_ZEPHYR_SYS_ITERABLE_SECTIONS_H_
8 : #define INCLUDE_ZEPHYR_SYS_ITERABLE_SECTIONS_H_
9 :
10 : #include <zephyr/sys/__assert.h>
11 : #include <zephyr/toolchain.h>
12 :
13 : #ifdef __cplusplus
14 : extern "C" {
15 : #endif
16 :
17 : /**
18 : * @brief Iterable Sections APIs
19 : * @defgroup iterable_section_apis Iterable Sections APIs
20 : * @ingroup os_services
21 : * @{
22 : */
23 :
24 : /**
25 : * @brief Defines a new element for an iterable section for a generic type.
26 : *
27 : * @details
28 : * Convenience helper combining __in_section() and Z_DECL_ALIGN().
29 : * The section name will be '.[SECNAME].static.[SECTION_POSTFIX]'
30 : *
31 : * In the linker script, create output sections for these using
32 : * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM().
33 : *
34 : * @note In order to store the element in ROM, a const specifier has to
35 : * be added to the declaration: const TYPE_SECTION_ITERABLE(...);
36 : *
37 : * @param[in] type data type of variable
38 : * @param[in] varname name of variable to place in section
39 : * @param[in] secname type name of iterable section.
40 : * @param[in] section_postfix postfix to use in section name
41 : */
42 1 : #define TYPE_SECTION_ITERABLE(type, varname, secname, section_postfix) \
43 : Z_DECL_ALIGN(type) varname \
44 : __in_section(_##secname, static, _CONCAT(section_postfix, _)) __used __noasan
45 :
46 : /**
47 : * @brief iterable section start symbol for a generic type
48 : *
49 : * will return '_[OUT_TYPE]_list_start'.
50 : *
51 : * @param[in] secname type name of iterable section. For 'struct foobar' this
52 : * would be TYPE_SECTION_START(foobar)
53 : *
54 : */
55 1 : #define TYPE_SECTION_START(secname) _CONCAT(_##secname, _list_start)
56 :
57 : /**
58 : * @brief iterable section end symbol for a generic type
59 : *
60 : * will return '_<SECNAME>_list_end'.
61 : *
62 : * @param[in] secname type name of iterable section. For 'struct foobar' this
63 : * would be TYPE_SECTION_START(foobar)
64 : */
65 1 : #define TYPE_SECTION_END(secname) _CONCAT(_##secname, _list_end)
66 :
67 : /**
68 : * @brief iterable section extern for start symbol for a generic type
69 : *
70 : * Helper macro to give extern for start of iterable section. The macro
71 : * typically will be called TYPE_SECTION_START_EXTERN(struct foobar, foobar).
72 : * This allows the macro to hand different types as well as cases where the
73 : * type and section name may differ.
74 : *
75 : * @param[in] type data type of section
76 : * @param[in] secname name of output section
77 : */
78 1 : #define TYPE_SECTION_START_EXTERN(type, secname) \
79 : extern type TYPE_SECTION_START(secname)[]
80 :
81 : /**
82 : * @brief iterable section extern for end symbol for a generic type
83 : *
84 : * Helper macro to give extern for end of iterable section. The macro
85 : * typically will be called TYPE_SECTION_END_EXTERN(struct foobar, foobar).
86 : * This allows the macro to hand different types as well as cases where the
87 : * type and section name may differ.
88 : *
89 : * @param[in] type data type of section
90 : * @param[in] secname name of output section
91 : */
92 1 : #define TYPE_SECTION_END_EXTERN(type, secname) \
93 : extern type TYPE_SECTION_END(secname)[]
94 :
95 : /**
96 : * @brief Iterate over a specified iterable section for a generic type
97 : *
98 : * @details
99 : * Iterator for structure instances gathered by TYPE_SECTION_ITERABLE().
100 : * The linker must provide a _<SECNAME>_list_start symbol and a
101 : * _<SECNAME>_list_end symbol to mark the start and the end of the
102 : * list of struct objects to iterate over. This is normally done using
103 : * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script.
104 : */
105 1 : #define TYPE_SECTION_FOREACH(type, secname, iterator) \
106 : TYPE_SECTION_START_EXTERN(type, secname); \
107 : TYPE_SECTION_END_EXTERN(type, secname); \
108 : for (type * iterator = TYPE_SECTION_START(secname); ({ \
109 : __ASSERT(iterator <= TYPE_SECTION_END(secname),\
110 : "unexpected list end location"); \
111 : iterator < TYPE_SECTION_END(secname); \
112 : }); \
113 : iterator++)
114 :
115 : /**
116 : * @brief Get element from section for a generic type.
117 : *
118 : * @note There is no protection against reading beyond the section.
119 : *
120 : * @param[in] type type of element
121 : * @param[in] secname name of output section
122 : * @param[in] i Index.
123 : * @param[out] dst Pointer to location where pointer to element is written.
124 : */
125 1 : #define TYPE_SECTION_GET(type, secname, i, dst) do { \
126 : TYPE_SECTION_START_EXTERN(type, secname); \
127 : *(dst) = &TYPE_SECTION_START(secname)[i]; \
128 : } while (0)
129 :
130 : /**
131 : * @brief Count elements in a section for a generic type.
132 : *
133 : * @param[in] type type of element
134 : * @param[in] secname name of output section
135 : * @param[out] dst Pointer to location where result is written.
136 : */
137 1 : #define TYPE_SECTION_COUNT(type, secname, dst) do { \
138 : TYPE_SECTION_START_EXTERN(type, secname); \
139 : TYPE_SECTION_END_EXTERN(type, secname); \
140 : *(dst) = ((uintptr_t)TYPE_SECTION_END(secname) - \
141 : (uintptr_t)TYPE_SECTION_START(secname)) / sizeof(type); \
142 : } while (0)
143 :
144 : /**
145 : * @brief iterable section start symbol for a struct type
146 : *
147 : * @param[in] struct_type data type of section
148 : */
149 1 : #define STRUCT_SECTION_START(struct_type) \
150 : TYPE_SECTION_START(struct_type)
151 :
152 : /**
153 : * @brief iterable section extern for start symbol for a struct
154 : *
155 : * Helper macro to give extern for start of iterable section.
156 : *
157 : * @param[in] struct_type data type of section
158 : */
159 1 : #define STRUCT_SECTION_START_EXTERN(struct_type) \
160 : TYPE_SECTION_START_EXTERN(struct struct_type, struct_type)
161 :
162 : /**
163 : * @brief iterable section end symbol for a struct type
164 : *
165 : * @param[in] struct_type data type of section
166 : */
167 1 : #define STRUCT_SECTION_END(struct_type) \
168 : TYPE_SECTION_END(struct_type)
169 :
170 : /**
171 : * @brief iterable section extern for end symbol for a struct
172 : *
173 : * Helper macro to give extern for end of iterable section.
174 : *
175 : * @param[in] struct_type data type of section
176 : */
177 1 : #define STRUCT_SECTION_END_EXTERN(struct_type) \
178 : TYPE_SECTION_END_EXTERN(struct struct_type, struct_type)
179 :
180 : /**
181 : * @brief Defines a new element of alternate data type for an iterable section.
182 : *
183 : * @details
184 : * Special variant of STRUCT_SECTION_ITERABLE(), for placing alternate
185 : * data types within the iterable section of a specific data type. The
186 : * data type sizes and semantics must be equivalent!
187 : */
188 1 : #define STRUCT_SECTION_ITERABLE_ALTERNATE(secname, struct_type, varname) \
189 : TYPE_SECTION_ITERABLE(struct struct_type, varname, secname, varname)
190 :
191 : /**
192 : * @brief Defines an array of elements of alternate data type for an iterable
193 : * section.
194 : *
195 : * @see STRUCT_SECTION_ITERABLE_ALTERNATE
196 : */
197 : #define STRUCT_SECTION_ITERABLE_ARRAY_ALTERNATE(secname, struct_type, varname, \
198 1 : size) \
199 : TYPE_SECTION_ITERABLE(struct struct_type, varname[size], secname, \
200 : varname)
201 :
202 : /**
203 : * @brief Defines a new element for an iterable section.
204 : *
205 : * @details
206 : * Convenience helper combining __in_section() and Z_DECL_ALIGN().
207 : * The section name is the struct type prepended with an underscore.
208 : * The subsection is "static" and the subsubsection is the variable name.
209 : *
210 : * In the linker script, create output sections for these using
211 : * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM().
212 : *
213 : * @note In order to store the element in ROM, a const specifier has to
214 : * be added to the declaration: const STRUCT_SECTION_ITERABLE(...);
215 : */
216 1 : #define STRUCT_SECTION_ITERABLE(struct_type, varname) \
217 : STRUCT_SECTION_ITERABLE_ALTERNATE(struct_type, struct_type, varname)
218 :
219 : /**
220 : * @brief Defines an array of elements for an iterable section.
221 : *
222 : * @see STRUCT_SECTION_ITERABLE
223 : */
224 1 : #define STRUCT_SECTION_ITERABLE_ARRAY(struct_type, varname, size) \
225 : STRUCT_SECTION_ITERABLE_ARRAY_ALTERNATE(struct_type, struct_type, \
226 : varname, size)
227 :
228 : /**
229 : * @brief Defines a new element for an iterable section with a custom name.
230 : *
231 : * The name can be used to customize how iterable section entries are sorted.
232 : * @see STRUCT_SECTION_ITERABLE()
233 : */
234 1 : #define STRUCT_SECTION_ITERABLE_NAMED(struct_type, name, varname) \
235 : TYPE_SECTION_ITERABLE(struct struct_type, varname, struct_type, name)
236 :
237 : /**
238 : * @brief Defines a new element for an iterable section with a custom name,
239 : * placed in a custom section.
240 : *
241 : * The name can be used to customize how iterable section entries are sorted.
242 : * @see STRUCT_SECTION_ITERABLE_NAMED()
243 : */
244 1 : #define STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE(struct_type, secname, name, varname) \
245 : TYPE_SECTION_ITERABLE(struct struct_type, varname, secname, name)
246 :
247 : /**
248 : * @brief Iterate over a specified iterable section (alternate).
249 : *
250 : * @details
251 : * Iterator for structure instances gathered by STRUCT_SECTION_ITERABLE().
252 : * The linker must provide a _<SECNAME>_list_start symbol and a
253 : * _<SECNAME>_list_end symbol to mark the start and the end of the
254 : * list of struct objects to iterate over. This is normally done using
255 : * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script.
256 : */
257 1 : #define STRUCT_SECTION_FOREACH_ALTERNATE(secname, struct_type, iterator) \
258 : TYPE_SECTION_FOREACH(struct struct_type, secname, iterator)
259 :
260 : /**
261 : * @brief Iterate over a specified iterable section.
262 : *
263 : * @details
264 : * Iterator for structure instances gathered by STRUCT_SECTION_ITERABLE().
265 : * The linker must provide a _<struct_type>_list_start symbol and a
266 : * _<struct_type>_list_end symbol to mark the start and the end of the
267 : * list of struct objects to iterate over. This is normally done using
268 : * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script.
269 : */
270 1 : #define STRUCT_SECTION_FOREACH(struct_type, iterator) \
271 : STRUCT_SECTION_FOREACH_ALTERNATE(struct_type, struct_type, iterator)
272 :
273 : /**
274 : * @brief Get element from section.
275 : *
276 : * @note There is no protection against reading beyond the section.
277 : *
278 : * @param[in] struct_type Struct type.
279 : * @param[in] i Index.
280 : * @param[out] dst Pointer to location where pointer to element is written.
281 : */
282 1 : #define STRUCT_SECTION_GET(struct_type, i, dst) \
283 : TYPE_SECTION_GET(struct struct_type, struct_type, i, dst)
284 :
285 : /**
286 : * @brief Count elements in a section.
287 : *
288 : * @param[in] struct_type Struct type
289 : * @param[out] dst Pointer to location where result is written.
290 : */
291 1 : #define STRUCT_SECTION_COUNT(struct_type, dst) \
292 : TYPE_SECTION_COUNT(struct struct_type, struct_type, dst);
293 :
294 : /**
295 : * @}
296 : */ /* end of struct_section_apis */
297 :
298 : #ifdef __cplusplus
299 : }
300 : #endif
301 :
302 : #endif /* INCLUDE_ZEPHYR_SYS_ITERABLE_SECTIONS_H_ */
|