| /* |
| * Copyright (C) 2020, Intel Corporation |
| * Copyright (C) 2023, Nordic Semiconductor ASA |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef INCLUDE_ZEPHYR_SYS_ITERABLE_SECTIONS_H_ |
| #define INCLUDE_ZEPHYR_SYS_ITERABLE_SECTIONS_H_ |
| |
| #include <zephyr/sys/__assert.h> |
| #include <zephyr/toolchain.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * @brief Iterable Sections APIs |
| * @defgroup iterable_section_apis Iterable Sections APIs |
| * @ingroup os_services |
| * @{ |
| */ |
| |
| /** |
| * @brief Defines a new element for an iterable section for a generic type. |
| * |
| * @details |
| * Convenience helper combining __in_section() and Z_DECL_ALIGN(). |
| * The section name will be '.[SECNAME].static.[SECTION_POSTFIX]' |
| * |
| * In the linker script, create output sections for these using |
| * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM(). |
| * |
| * @note In order to store the element in ROM, a const specifier has to |
| * be added to the declaration: const TYPE_SECTION_ITERABLE(...); |
| * |
| * @param[in] type data type of variable |
| * @param[in] varname name of variable to place in section |
| * @param[in] secname type name of iterable section. |
| * @param[in] section_postfix postfix to use in section name |
| */ |
| #define TYPE_SECTION_ITERABLE(type, varname, secname, section_postfix) \ |
| Z_DECL_ALIGN(type) varname \ |
| __in_section(_##secname, static, _CONCAT(section_postfix, _)) __used __noasan |
| |
| /** |
| * @brief iterable section start symbol for a generic type |
| * |
| * will return '_[OUT_TYPE]_list_start'. |
| * |
| * @param[in] secname type name of iterable section. For 'struct foobar' this |
| * would be TYPE_SECTION_START(foobar) |
| * |
| */ |
| #define TYPE_SECTION_START(secname) _CONCAT(_##secname, _list_start) |
| |
| /** |
| * @brief iterable section end symbol for a generic type |
| * |
| * will return '_<SECNAME>_list_end'. |
| * |
| * @param[in] secname type name of iterable section. For 'struct foobar' this |
| * would be TYPE_SECTION_START(foobar) |
| */ |
| #define TYPE_SECTION_END(secname) _CONCAT(_##secname, _list_end) |
| |
| /** |
| * @brief iterable section extern for start symbol for a generic type |
| * |
| * Helper macro to give extern for start of iterable section. The macro |
| * typically will be called TYPE_SECTION_START_EXTERN(struct foobar, foobar). |
| * This allows the macro to hand different types as well as cases where the |
| * type and section name may differ. |
| * |
| * @param[in] type data type of section |
| * @param[in] secname name of output section |
| */ |
| #define TYPE_SECTION_START_EXTERN(type, secname) \ |
| extern type TYPE_SECTION_START(secname)[] |
| |
| /** |
| * @brief iterable section extern for end symbol for a generic type |
| * |
| * Helper macro to give extern for end of iterable section. The macro |
| * typically will be called TYPE_SECTION_END_EXTERN(struct foobar, foobar). |
| * This allows the macro to hand different types as well as cases where the |
| * type and section name may differ. |
| * |
| * @param[in] type data type of section |
| * @param[in] secname name of output section |
| */ |
| #define TYPE_SECTION_END_EXTERN(type, secname) \ |
| extern type TYPE_SECTION_END(secname)[] |
| |
| /** |
| * @brief Iterate over a specified iterable section for a generic type |
| * |
| * @details |
| * Iterator for structure instances gathered by TYPE_SECTION_ITERABLE(). |
| * The linker must provide a _<SECNAME>_list_start symbol and a |
| * _<SECNAME>_list_end symbol to mark the start and the end of the |
| * list of struct objects to iterate over. This is normally done using |
| * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script. |
| */ |
| #define TYPE_SECTION_FOREACH(type, secname, iterator) \ |
| TYPE_SECTION_START_EXTERN(type, secname); \ |
| TYPE_SECTION_END_EXTERN(type, secname); \ |
| for (type * iterator = TYPE_SECTION_START(secname); ({ \ |
| __ASSERT(iterator <= TYPE_SECTION_END(secname),\ |
| "unexpected list end location"); \ |
| iterator < TYPE_SECTION_END(secname); \ |
| }); \ |
| iterator++) |
| |
| /** |
| * @brief Get element from section for a generic type. |
| * |
| * @note There is no protection against reading beyond the section. |
| * |
| * @param[in] type type of element |
| * @param[in] secname name of output section |
| * @param[in] i Index. |
| * @param[out] dst Pointer to location where pointer to element is written. |
| */ |
| #define TYPE_SECTION_GET(type, secname, i, dst) do { \ |
| TYPE_SECTION_START_EXTERN(type, secname); \ |
| *(dst) = &TYPE_SECTION_START(secname)[i]; \ |
| } while (0) |
| |
| /** |
| * @brief Count elements in a section for a generic type. |
| * |
| * @param[in] type type of element |
| * @param[in] secname name of output section |
| * @param[out] dst Pointer to location where result is written. |
| */ |
| #define TYPE_SECTION_COUNT(type, secname, dst) do { \ |
| TYPE_SECTION_START_EXTERN(type, secname); \ |
| TYPE_SECTION_END_EXTERN(type, secname); \ |
| *(dst) = ((uintptr_t)TYPE_SECTION_END(secname) - \ |
| (uintptr_t)TYPE_SECTION_START(secname)) / sizeof(type); \ |
| } while (0) |
| |
| /** |
| * @brief iterable section start symbol for a struct type |
| * |
| * @param[in] struct_type data type of section |
| */ |
| #define STRUCT_SECTION_START(struct_type) \ |
| TYPE_SECTION_START(struct_type) |
| |
| /** |
| * @brief iterable section extern for start symbol for a struct |
| * |
| * Helper macro to give extern for start of iterable section. |
| * |
| * @param[in] struct_type data type of section |
| */ |
| #define STRUCT_SECTION_START_EXTERN(struct_type) \ |
| TYPE_SECTION_START_EXTERN(struct struct_type, struct_type) |
| |
| /** |
| * @brief iterable section end symbol for a struct type |
| * |
| * @param[in] struct_type data type of section |
| */ |
| #define STRUCT_SECTION_END(struct_type) \ |
| TYPE_SECTION_END(struct_type) |
| |
| /** |
| * @brief iterable section extern for end symbol for a struct |
| * |
| * Helper macro to give extern for end of iterable section. |
| * |
| * @param[in] struct_type data type of section |
| */ |
| #define STRUCT_SECTION_END_EXTERN(struct_type) \ |
| TYPE_SECTION_END_EXTERN(struct struct_type, struct_type) |
| |
| /** |
| * @brief Defines a new element of alternate data type for an iterable section. |
| * |
| * @details |
| * Special variant of STRUCT_SECTION_ITERABLE(), for placing alternate |
| * data types within the iterable section of a specific data type. The |
| * data type sizes and semantics must be equivalent! |
| */ |
| #define STRUCT_SECTION_ITERABLE_ALTERNATE(secname, struct_type, varname) \ |
| TYPE_SECTION_ITERABLE(struct struct_type, varname, secname, varname) |
| |
| /** |
| * @brief Defines an array of elements of alternate data type for an iterable |
| * section. |
| * |
| * @see STRUCT_SECTION_ITERABLE_ALTERNATE |
| */ |
| #define STRUCT_SECTION_ITERABLE_ARRAY_ALTERNATE(secname, struct_type, varname, \ |
| size) \ |
| TYPE_SECTION_ITERABLE(struct struct_type, varname[size], secname, \ |
| varname) |
| |
| /** |
| * @brief Defines a new element for an iterable section. |
| * |
| * @details |
| * Convenience helper combining __in_section() and Z_DECL_ALIGN(). |
| * The section name is the struct type prepended with an underscore. |
| * The subsection is "static" and the subsubsection is the variable name. |
| * |
| * In the linker script, create output sections for these using |
| * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM(). |
| * |
| * @note In order to store the element in ROM, a const specifier has to |
| * be added to the declaration: const STRUCT_SECTION_ITERABLE(...); |
| */ |
| #define STRUCT_SECTION_ITERABLE(struct_type, varname) \ |
| STRUCT_SECTION_ITERABLE_ALTERNATE(struct_type, struct_type, varname) |
| |
| /** |
| * @brief Defines an array of elements for an iterable section. |
| * |
| * @see STRUCT_SECTION_ITERABLE |
| */ |
| #define STRUCT_SECTION_ITERABLE_ARRAY(struct_type, varname, size) \ |
| STRUCT_SECTION_ITERABLE_ARRAY_ALTERNATE(struct_type, struct_type, \ |
| varname, size) |
| |
| /** |
| * @brief Defines a new element for an iterable section with a custom name. |
| * |
| * The name can be used to customize how iterable section entries are sorted. |
| * @see STRUCT_SECTION_ITERABLE() |
| */ |
| #define STRUCT_SECTION_ITERABLE_NAMED(struct_type, name, varname) \ |
| TYPE_SECTION_ITERABLE(struct struct_type, varname, struct_type, name) |
| |
| /** |
| * @brief Iterate over a specified iterable section (alternate). |
| * |
| * @details |
| * Iterator for structure instances gathered by STRUCT_SECTION_ITERABLE(). |
| * The linker must provide a _<SECNAME>_list_start symbol and a |
| * _<SECNAME>_list_end symbol to mark the start and the end of the |
| * list of struct objects to iterate over. This is normally done using |
| * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script. |
| */ |
| #define STRUCT_SECTION_FOREACH_ALTERNATE(secname, struct_type, iterator) \ |
| TYPE_SECTION_FOREACH(struct struct_type, secname, iterator) |
| |
| /** |
| * @brief Iterate over a specified iterable section. |
| * |
| * @details |
| * Iterator for structure instances gathered by STRUCT_SECTION_ITERABLE(). |
| * The linker must provide a _<struct_type>_list_start symbol and a |
| * _<struct_type>_list_end symbol to mark the start and the end of the |
| * list of struct objects to iterate over. This is normally done using |
| * ITERABLE_SECTION_ROM() or ITERABLE_SECTION_RAM() in the linker script. |
| */ |
| #define STRUCT_SECTION_FOREACH(struct_type, iterator) \ |
| STRUCT_SECTION_FOREACH_ALTERNATE(struct_type, struct_type, iterator) |
| |
| /** |
| * @brief Get element from section. |
| * |
| * @note There is no protection against reading beyond the section. |
| * |
| * @param[in] struct_type Struct type. |
| * @param[in] i Index. |
| * @param[out] dst Pointer to location where pointer to element is written. |
| */ |
| #define STRUCT_SECTION_GET(struct_type, i, dst) \ |
| TYPE_SECTION_GET(struct struct_type, struct_type, i, dst) |
| |
| /** |
| * @brief Count elements in a section. |
| * |
| * @param[in] struct_type Struct type |
| * @param[out] dst Pointer to location where result is written. |
| */ |
| #define STRUCT_SECTION_COUNT(struct_type, dst) \ |
| TYPE_SECTION_COUNT(struct struct_type, struct_type, dst); |
| |
| /** |
| * @} |
| */ /* end of struct_section_apis */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* INCLUDE_ZEPHYR_SYS_ITERABLE_SECTIONS_H_ */ |