1 /* 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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 #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 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 #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 #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 #define STRUCT_SECTION_ITERABLE_NAMED(struct_type, name, varname) \ 235 TYPE_SECTION_ITERABLE(struct struct_type, varname, struct_type, name) 236 237 /** 238 * @brief Iterate over a specified iterable section (alternate). 239 * 240 * @details 241 * Iterator for structure instances gathered by STRUCT_SECTION_ITERABLE(). 242 * The linker must provide a _<SECNAME>_list_start symbol and a 243 * _<SECNAME>_list_end symbol to mark the start and the end of the 244 * list of struct objects to iterate over. This is normally done using 245 * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script. 246 */ 247 #define STRUCT_SECTION_FOREACH_ALTERNATE(secname, struct_type, iterator) \ 248 TYPE_SECTION_FOREACH(struct struct_type, secname, iterator) 249 250 /** 251 * @brief Iterate over a specified iterable section. 252 * 253 * @details 254 * Iterator for structure instances gathered by STRUCT_SECTION_ITERABLE(). 255 * The linker must provide a _<struct_type>_list_start symbol and a 256 * _<struct_type>_list_end symbol to mark the start and the end of the 257 * list of struct objects to iterate over. This is normally done using 258 * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script. 259 */ 260 #define STRUCT_SECTION_FOREACH(struct_type, iterator) \ 261 STRUCT_SECTION_FOREACH_ALTERNATE(struct_type, struct_type, iterator) 262 263 /** 264 * @brief Get element from section. 265 * 266 * @note There is no protection against reading beyond the section. 267 * 268 * @param[in] struct_type Struct type. 269 * @param[in] i Index. 270 * @param[out] dst Pointer to location where pointer to element is written. 271 */ 272 #define STRUCT_SECTION_GET(struct_type, i, dst) \ 273 TYPE_SECTION_GET(struct struct_type, struct_type, i, dst) 274 275 /** 276 * @brief Count elements in a section. 277 * 278 * @param[in] struct_type Struct type 279 * @param[out] dst Pointer to location where result is written. 280 */ 281 #define STRUCT_SECTION_COUNT(struct_type, dst) \ 282 TYPE_SECTION_COUNT(struct struct_type, struct_type, dst); 283 284 /** 285 * @} 286 */ /* end of struct_section_apis */ 287 288 #ifdef __cplusplus 289 } 290 #endif 291 292 #endif /* INCLUDE_ZEPHYR_SYS_ITERABLE_SECTIONS_H_ */ 293