xref: /dpdk/lib/eal/include/rte_lcore_var.h (revision 37dda90ee15b7098bc48356868a87d34f727eecc)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2024 Ericsson AB
3  */
4 
5 #ifndef RTE_LCORE_VAR_H
6 #define RTE_LCORE_VAR_H
7 
8 /**
9  * @file
10  *
11  * Lcore variables
12  *
13  * This API provides a mechanism to create and access per-lcore id
14  * variables in a space- and cycle-efficient manner.
15  *
16  * Please refer to the lcore variables' programmer's guide
17  * for an overview of this API and its implementation.
18  *
19  * EXPERIMENTAL: this API may change, or be removed, without prior notice.
20  */
21 
22 #include <stddef.h>
23 #include <stdalign.h>
24 
25 #include <rte_common.h>
26 #include <rte_config.h>
27 #include <rte_lcore.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /**
34  * Given the lcore variable type, produces the type of the lcore variable handle.
35  */
36 #define RTE_LCORE_VAR_HANDLE_TYPE(type)		\
37 	type *
38 
39 /**
40  * Define an lcore variable handle.
41  *
42  * This macro defines a variable which is used as a handle
43  * to access the various instances of a per-lcore id variable.
44  *
45  * This macro clarifies that the declaration is an lcore handle,
46  * not a regular pointer.
47  *
48  * Add @b static as a prefix in case the lcore variable
49  * is only to be accessed from a particular translation unit.
50  */
51 #define RTE_LCORE_VAR_HANDLE(type, name)	\
52 	RTE_LCORE_VAR_HANDLE_TYPE(type) name
53 
54 /**
55  * Allocate space for an lcore variable, and initialize its handle.
56  *
57  * The values of the lcore variable are initialized to zero.
58  */
59 #define RTE_LCORE_VAR_ALLOC_SIZE_ALIGN(handle, size, align)	\
60 	handle = rte_lcore_var_alloc(size, align)
61 
62 /**
63  * Allocate space for an lcore variable, and initialize its handle,
64  * with values aligned for any type of object.
65  *
66  * The values of the lcore variable are initialized to zero.
67  */
68 #define RTE_LCORE_VAR_ALLOC_SIZE(handle, size)	\
69 	RTE_LCORE_VAR_ALLOC_SIZE_ALIGN(handle, size, 0)
70 
71 /**
72  * Allocate space for an lcore variable of the size and alignment requirements
73  * suggested by the handle pointer type, and initialize its handle.
74  *
75  * The values of the lcore variable are initialized to zero.
76  */
77 #define RTE_LCORE_VAR_ALLOC(handle)					\
78 	RTE_LCORE_VAR_ALLOC_SIZE_ALIGN(handle, sizeof(*(handle)),	\
79 				       alignof(typeof(*(handle))))
80 
81 /**
82  * Allocate an explicitly-sized, explicitly-aligned lcore variable
83  * by means of a @ref RTE_INIT constructor.
84  *
85  * The values of the lcore variable are initialized to zero.
86  */
87 #define RTE_LCORE_VAR_INIT_SIZE_ALIGN(name, size, align)		\
88 	RTE_INIT(rte_lcore_var_init_ ## name)				\
89 	{								\
90 		RTE_LCORE_VAR_ALLOC_SIZE_ALIGN(name, size, align);	\
91 	}
92 
93 /**
94  * Allocate an explicitly-sized lcore variable
95  * by means of a @ref RTE_INIT constructor.
96  *
97  * The values of the lcore variable are initialized to zero.
98  */
99 #define RTE_LCORE_VAR_INIT_SIZE(name, size)		\
100 	RTE_LCORE_VAR_INIT_SIZE_ALIGN(name, size, 0)
101 
102 /**
103  * Allocate an lcore variable by means of a @ref RTE_INIT constructor.
104  *
105  * The values of the lcore variable are initialized to zero.
106  */
107 #define RTE_LCORE_VAR_INIT(name)					\
108 	RTE_INIT(rte_lcore_var_init_ ## name)				\
109 	{								\
110 		RTE_LCORE_VAR_ALLOC(name);				\
111 	}
112 
113 /**
114  * Get void pointer to lcore variable instance with the specified lcore id.
115  *
116  * @param lcore_id
117  *   The lcore id specifying which of the @c RTE_MAX_LCORE value
118  *   instances should be accessed. The lcore id need not be valid
119  *   (e.g., may be @ref LCORE_ID_ANY), but in such a case,
120  *   the pointer is also not valid (and thus should not be dereferenced).
121  * @param handle
122  *   The lcore variable handle.
123  */
124 /* access function 8< */
125 static inline void *
126 rte_lcore_var_lcore(unsigned int lcore_id, void *handle)
127 {
128 	return RTE_PTR_ADD(handle, lcore_id * RTE_MAX_LCORE_VAR);
129 }
130 /* >8 end of access function */
131 
132 /**
133  * Get pointer to lcore variable instance with the specified lcore id.
134  *
135  * @param lcore_id
136  *   The lcore id specifying which of the @c RTE_MAX_LCORE value
137  *   instances should be accessed. The lcore id need not be valid
138  *   (e.g., may be @ref LCORE_ID_ANY), but in such a case,
139  *   the pointer is also not valid (and thus should not be dereferenced).
140  * @param handle
141  *   The lcore variable handle.
142  */
143 #define RTE_LCORE_VAR_LCORE(lcore_id, handle)			\
144 	((typeof(handle))rte_lcore_var_lcore(lcore_id, handle))
145 
146 /**
147  * Get pointer to lcore variable instance of the current thread.
148  *
149  * May only be used by EAL threads and registered non-EAL threads.
150  */
151 #define RTE_LCORE_VAR(handle)				\
152 	RTE_LCORE_VAR_LCORE(rte_lcore_id(), handle)
153 
154 /**
155  * Iterate over each lcore id's value for an lcore variable.
156  *
157  * @param lcore_id
158  *   An <code>unsigned int</code> variable successively set to the
159  *   lcore id of every valid lcore id (up to @c RTE_MAX_LCORE).
160  * @param value
161  *   A pointer variable successively set to point to lcore variable
162  *   value instance of the current lcore id being processed.
163  * @param handle
164  *   The lcore variable handle.
165  */
166 #define RTE_LCORE_VAR_FOREACH(lcore_id, value, handle)			\
167 	for ((lcore_id) =						\
168 		     (((value) = RTE_LCORE_VAR_LCORE(0, handle)), 0); \
169 	     (lcore_id) < RTE_MAX_LCORE;				\
170 	     (lcore_id)++, (value) = RTE_LCORE_VAR_LCORE(lcore_id, \
171 							       handle))
172 
173 /**
174  * Allocate space in the per-lcore id buffers for an lcore variable.
175  *
176  * The pointer returned is only an opaque identifier of the variable.
177  * To get an actual pointer to a particular instance of the variable,
178  * use @ref RTE_LCORE_VAR or @ref RTE_LCORE_VAR_LCORE.
179  *
180  * The lcore variable values' memory is set to zero.
181  *
182  * The allocation is always successful,
183  * barring a fatal exhaustion of the per-lcore id buffer space.
184  *
185  * rte_lcore_var_alloc() is not multi-thread safe.
186  *
187  * The allocated memory cannot be freed.
188  *
189  * @param size
190  *   The size (in bytes) of the variable's per-lcore id value. Must be > 0.
191  * @param align
192  *   If 0, the values will be suitably aligned for any kind of type
193  *   (i.e., alignof(max_align_t)). Otherwise, the values will be aligned
194  *   on a multiple of *align*, which must be a power of 2
195  *   and equal or less than @c RTE_CACHE_LINE_SIZE.
196  * @return
197  *   The variable's handle, stored in a void pointer value.
198  *   The value is always non-NULL.
199  */
200 __rte_experimental
201 void *
202 rte_lcore_var_alloc(size_t size, size_t align)
203 	__rte_alloc_size(1) __rte_alloc_align(2);
204 
205 #ifdef __cplusplus
206 }
207 #endif
208 
209 #endif /* RTE_LCORE_VAR_H */
210