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