LCOV - code coverage report
Current view: top level - zephyr/sys - iterable_sections.h Hit Total Coverage
Test: new.info Lines: 22 23 95.7 %
Date: 2024-12-22 00:14:23

          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_ */

Generated by: LCOV version 1.14