1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2024 Ericsson AB 3 */ 4 5 #include <inttypes.h> 6 #include <stdlib.h> 7 8 #ifdef RTE_EXEC_ENV_WINDOWS 9 #include <malloc.h> 10 #endif 11 12 #include <rte_common.h> 13 #include <rte_debug.h> 14 #include <rte_log.h> 15 16 #include <rte_lcore_var.h> 17 18 #include "eal_private.h" 19 #include "eal_lcore_var.h" 20 21 /* 22 * Refer to the programmer's guide for an overview 23 * of the lcore variables implementation. 24 */ 25 26 /* base unit */ 27 struct lcore_var_buffer { 28 char data[RTE_MAX_LCORE_VAR * RTE_MAX_LCORE]; 29 struct lcore_var_buffer *prev; 30 }; 31 32 /* last allocated unit */ 33 static struct lcore_var_buffer *current_buffer; 34 35 /* initialized to trigger buffer allocation on first allocation */ 36 static size_t offset = RTE_MAX_LCORE_VAR; 37 38 /* >8 end of documented variables */ 39 40 static void * 41 lcore_var_alloc(size_t size, size_t align) 42 { 43 void *handle; 44 unsigned int lcore_id; 45 void *value; 46 47 offset = RTE_ALIGN_CEIL(offset, align); 48 49 if (offset + size > RTE_MAX_LCORE_VAR) { 50 struct lcore_var_buffer *prev = current_buffer; 51 size_t alloc_size = 52 RTE_ALIGN_CEIL(sizeof(struct lcore_var_buffer), RTE_CACHE_LINE_SIZE); 53 #ifdef RTE_EXEC_ENV_WINDOWS 54 current_buffer = _aligned_malloc(alloc_size, RTE_CACHE_LINE_SIZE); 55 #else 56 current_buffer = aligned_alloc(RTE_CACHE_LINE_SIZE, alloc_size); 57 #endif 58 RTE_VERIFY(current_buffer != NULL); 59 60 current_buffer->prev = prev; 61 62 offset = 0; 63 } 64 65 handle = ¤t_buffer->data[offset]; 66 67 offset += size; 68 69 RTE_LCORE_VAR_FOREACH(lcore_id, value, handle) 70 memset(value, 0, size); 71 72 EAL_LOG(DEBUG, "Allocated %"PRIuPTR" bytes of per-lcore data with a " 73 "%"PRIuPTR"-byte alignment", size, align); 74 75 return handle; 76 } 77 78 void * 79 rte_lcore_var_alloc(size_t size, size_t align) 80 { 81 /* Having the per-lcore buffer size aligned on cache lines 82 * assures as well as having the base pointer aligned on cache size 83 * assures that aligned offsets also translate to aligned pointers 84 * across all values. 85 */ 86 RTE_BUILD_BUG_ON(RTE_MAX_LCORE_VAR % RTE_CACHE_LINE_SIZE != 0); 87 RTE_VERIFY(align <= RTE_CACHE_LINE_SIZE); 88 RTE_VERIFY(size <= RTE_MAX_LCORE_VAR); 89 90 /* '0' means asking for worst-case alignment requirements */ 91 if (align == 0) 92 #ifdef RTE_TOOLCHAIN_MSVC 93 /* MSVC <stddef.h> is missing the max_align_t typedef */ 94 align = alignof(double); 95 #else 96 align = alignof(max_align_t); 97 #endif 98 99 RTE_VERIFY(rte_is_power_of_2(align)); 100 101 return lcore_var_alloc(size, align); 102 } 103 104 void 105 eal_lcore_var_cleanup(void) 106 { 107 while (current_buffer != NULL) { 108 struct lcore_var_buffer *prev = current_buffer->prev; 109 110 #ifdef RTE_EXEC_ENV_WINDOWS 111 _aligned_free(current_buffer); 112 #else 113 free(current_buffer); 114 #endif 115 116 current_buffer = prev; 117 } 118 } 119