aboutsummaryrefslogtreecommitdiff
path: root/core/include/scattered_array.h
blob: 812583d00f5b799a53e328ae522fe46523e19925 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* SPDX-License-Identifier: BSD-2-Clause */
/*
 * Copyright (c) 2018, Linaro Limited
 */
#ifndef __SCATTERED_ARRAY_H
#define __SCATTERED_ARRAY_H

#include <compiler.h>
#include <keep.h>

/*
 * A scattered array is assembled from items declared in different source
 * files depending on something like "SORT(.scattered_array*)" in the link
 * script to get everything assembled in the right order.
 *
 * Whenever a new scattered array is created with the macros below there's
 * no need to update the link script.
 */

#define __SCT_ARRAY_DEF_ITEM3(element_type, element_name, section_name) \
	static const element_type element_name; \
	KEEP_INIT(element_name); \
	static const element_type element_name __used \
		__section(section_name __SECTION_FLAGS_RODATA)

#define __SCT_ARRAY_DEF_PG_ITEM3(element_type, element_name, section_name) \
	static const element_type element_name __used \
		__section(section_name __SECTION_FLAGS_RODATA)

#define __SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type) \
	__SCT_ARRAY_DEF_ITEM3(element_type, \
			      __scattered_array_ ## id ## array_name, \
			      ".scattered_array_" #array_name "_1_" #order)

#define __SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type) \
	__SCT_ARRAY_DEF_PG_ITEM3(element_type, \
				 __scattered_array_ ## id ## array_name, \
				 ".scattered_array_" #array_name "_1_" #order)

#define __SCT_ARRAY_DEF_ITEM1(array_name, order, id, element_type) \
	__SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type)

#define __SCT_ARRAY_DEF_PG_ITEM1(array_name, order, id, element_type) \
	__SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type)

/*
 * Defines an item in a scattered array, sorted based on @order.
 * @array_name:   Name of the scattered array
 * @order:        Tag on which this item is sorted in the array
 * @element_type: The type of the elemenet
 */
#define SCATTERED_ARRAY_DEFINE_ITEM_ORDERED(array_name, order, element_type) \
	__SCT_ARRAY_DEF_ITEM1(array_name, order, __COUNTER__, element_type)

/*
 * Same as SCATTERED_ARRAY_DEFINE_ITEM_ORDERED except that references
 * to other objects (for instance null terminated strings) are allowed
 * to reside in the paged area without residing in the init area
 */
#define SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(array_name, order, \
					       element_type) \
	__SCT_ARRAY_DEF_PG_ITEM1(array_name, order, __COUNTER__, element_type)

/*
 * Defines an item in a scattered array
 * @array_name:   Name of the scattered array
 * @element_type: The type of the elemenet
 */
#define SCATTERED_ARRAY_DEFINE_ITEM(array_name, element_type) \
	__SCT_ARRAY_DEF_ITEM1(array_name, 0, __COUNTER__, element_type)

/*
 * Same as SCATTERED_ARRAY_DEFINE_ITEM except that references to other
 * objects (for instance null terminated strings) are allowed to reside in
 * the paged area without residing in the init area
 */
#define SCATTERED_ARRAY_DEFINE_PG_ITEM(array_name, element_type) \
	__SCT_ARRAY_DEF_PG_ITEM1(array_name, 0, __COUNTER__, element_type)

/*
 * Returns the first element in a scattered array
 * @array_name:   Name of the scattered array
 * @element_type: The type of the elemenet
 */
#define SCATTERED_ARRAY_BEGIN(array_name, element_type) (__extension__({ \
		static const element_type __scattered_array_begin[0] __unused \
		__section(".scattered_array_" #array_name "_0" \
			  __SECTION_FLAGS_RODATA); \
		\
		(const element_type *)scattered_array_relax_ptr( \
			__scattered_array_begin); \
	}))

/*
 * Returns one entry past the last element in a scattered array
 * @array_name:   Name of the scattered array
 * @element_type: The type of the elemenet
 */
#define SCATTERED_ARRAY_END(array_name, element_type) (__extension__({ \
		static const element_type __scattered_array_end[0] __unused \
		__section(".scattered_array_" #array_name "_2" \
			  __SECTION_FLAGS_RODATA); \
		\
		__scattered_array_end; \
	}))

/*
 * Loop over all elements in the scattered array
 * @elem:	Iterator
 * @array_name:   Name of the scattered array
 * @element_type: The type of the elemenet
 */
#define SCATTERED_ARRAY_FOREACH(elem, array_name, element_type) \
	for ((elem) = SCATTERED_ARRAY_BEGIN(array_name, element_type); \
	     (elem) < SCATTERED_ARRAY_END(array_name, element_type); (elem)++)

/*
 * scattered_array_relax_ptr() - relax pointer attributes
 * @p	pointer to return
 *
 * If the pointer returned from the array __scattered_array_begin[] in
 * SCATTERED_ARRAY_BEGIN() is passed directly the compiler may notice that
 * it's an empty array and emit warnings. With the address passed via this
 * function the compiler will have no such knowledge about the pointer.
 *
 * Returns supplied pointer.
 */
const void *scattered_array_relax_ptr(const void *p) __attr_const;

#endif /*__SCATTERED_ARRAY_H*/