This is an automated email from the ASF dual-hosted git repository. jerzy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 822cf1a019acab6ecd9160c5a8d900fccd8d1049 Author: Jerzy Kasenberg <[email protected]> AuthorDate: Fri May 23 23:05:35 2025 +0200 util: Add link table support macros This adds macros that help with link time generated tables. Signed-off-by: Jerzy Kasenberg <[email protected]> --- kernel/os/include/os/link_tables.h | 159 +++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/kernel/os/include/os/link_tables.h b/kernel/os/include/os/link_tables.h new file mode 100644 index 000000000..13c329611 --- /dev/null +++ b/kernel/os/include/os/link_tables.h @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_OS_LINK_TABLES_ +#define H_OS_LINK_TABLES_ + +/** + * @brief Helper macros for accessing link time tables + * + * Link time tables are compile time constant tables that are + * constructed during linking aggregating symbols for specific + * linker section. + * Object put in the section should be of the same size to be + * treated as array elements. + * + * To create named section that can be used as link time table + * without manual modification of linker script newt tool + * recognizes following section in pkg.yml + * + * pkg.link_tables: + * - example_table1 + * - example_table2 + * + * This creates entries in autogenerated linker script include file + * link_table.ld.h, those entries gather symbol of sections names: + * .example_table1 + * .example_table1.* + * and + * .example_table2 + * .example_table2.* + * + * To put element in those section user code can specify section + * name in variable definition. + * + * Following macro creates external table that can be access just + * as it would be defined explicitly. + * + * struct foo { + * int bar; + * }; + + * LINK_TABLE(struct foo, example1_table) + * LINK_TABLE(uint32_t, example2_table) + * + * Declares tables that are equivalent to: + * + * const struct foo example1_table[size1]; + * const uint32_t example2_table[size2]; + * + * Size of table is unknown at compile time but can be determined + * in runtime, depending on how many elements are actually put + * in those arrays. + * + * To put element in such array user code has to specify matching + * section name. It can be done in many ways i.e.: + * + * const struct foo foo1 __attribute__((section(".example1_table"), used)) = {1}; + * const struct foo foo2 LINK_TABLE_SECTION(example1_table) = {2}; + * const struct foo foo3 LINK_TABLE_ELEMENT_SECTION(example1_table, foo3) = {3}; + * LINK_TABLE_ELEMENT(example1_table, foo4) = {4}; + * + * const uint32_t elem1 LINK_TABLE_SECTION(example2_table) = 1; + * const uint32_t elem2 LINK_TABLE_ELEMENT_SECTION(example2_table, elem2) = 2; + * LINK_TABLE_ELEMENT(example_table2, elem3) = 3; + */ + +/* Macro change table name to actual symbol generated in link_tables.ld.h */ +#define LINK_TABLE_START(table_name) __##table_name##_start__ +/* Macro change table name to actual symbol generated in link_tables.ld.h */ +#define LINK_TABLE_END(table_name) __##table_name##_end__ +#define LINK_TABLE_SIZE(table_name) table_name##_size() +/* Macro to create typedef for element in table. + * Typedef name is constructed from table name and this allows to use table + * later on without specifying element type + */ +#define LINK_TABLE_ELEMENT_TYPE(table_name) table_name##_element_t +/* Macro to create symbol attribute for table */ +#define LINK_TABLE_SECTION(table_name) \ + __attribute__((section("." #table_name), used)) +/* Macro to create attribute for table with name that may affect order of elements */ +#define LINK_TABLE_ELEMENT_SECTION(table_name, elem) \ + __attribute__((section("." #table_name "." #elem))) +/* Macro to create element that goes to link table. + * It could be used like this: + * LINK_TABLE_ELEMENT(example1_table, foo5) = { + * .bar = 1; + * } + * This create element in table that also has distinct name that can be used directly. + */ +#define LINK_TABLE_ELEMENT(table_name, elem) \ + const LINK_TABLE_ELEMENT_TYPE(table_name) elem LINK_TABLE_ELEMENT_SECTION( \ + table_name, elem) +/* + * Macro to add existing element to link table via pointer. + * To have table with pointers to struct like this: + * struct base_struct { + * int a, b; + * } + * LINK_TABLE(struct base_struct *, pointer_array) + * + * Now create element that will go to pointer table + * struct base_struct naked_element; + * struct complex { + * const char *name; + * struct base_struct base; + * } complex_obj; + * + * LINK_TABLE_ELEMENT_REF(pointer_array, any_name, naked_element) + * LINK_TABLE_ELEMENT_REF(pointer_array, complex, complex_obj.base) + */ +#define LINK_TABLE_ELEMENT_REF(table_name, elem, var) \ + LINK_TABLE_ELEMENT_TYPE(table_name) \ + const elem##_ptr LINK_TABLE_ELEMENT_SECTION(table_name, elem) = &var + +#define LINK_TABLE(element_type, table_name) \ + typedef element_type table_name##_element_t; \ + extern element_type const table_name[]; \ + extern element_type const LINK_TABLE_START(table_name)[]; \ + extern element_type const LINK_TABLE_END(table_name)[]; \ + static inline size_t table_name##_size(void) \ + { \ + return LINK_TABLE_END(table_name) - LINK_TABLE_START(table_name); \ + } + +/** + * Simple inline loop for link table elements + * + * @param e - pointer variable name that can be used inside loop to access element + * @param table - link table to iterate over + */ +#define LINK_TABLE_FOREACH(e, table) \ + for (const LINK_TABLE_ELEMENT_TYPE(table) *e = table; \ + e != LINK_TABLE_END(table); ++e) + +/** + * Call fun for all element in link table. + */ +#define LINK_TABLE_FOREACH_CALL(table, fun) \ + LINK_TABLE_FOREACH(e, table) { \ + fun(e); \ + } + +#endif
