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

Reply via email to