1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2015 Intel Corporation 3 */ 4 #ifndef LTHREAD_OBJCACHE_H_ 5 #define LTHREAD_OBJCACHE_H_ 6 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 11 #include <string.h> 12 13 #include <rte_per_lcore.h> 14 #include <rte_malloc.h> 15 #include <rte_memory.h> 16 17 #include "lthread_int.h" 18 #include "lthread_diag.h" 19 #include "lthread_queue.h" 20 21 22 RTE_DECLARE_PER_LCORE(struct lthread_sched *, this_sched); 23 24 struct lthread_objcache { 25 struct lthread_queue *q; 26 size_t obj_size; 27 int prealloc_size; 28 char name[LT_MAX_NAME_SIZE]; 29 30 DIAG_COUNT_DEFINE(rd); 31 DIAG_COUNT_DEFINE(wr); 32 DIAG_COUNT_DEFINE(prealloc); 33 DIAG_COUNT_DEFINE(capacity); 34 DIAG_COUNT_DEFINE(available); 35 }; 36 37 /* 38 * Create a cache 39 */ 40 static inline struct 41 lthread_objcache *_lthread_objcache_create(const char *name, 42 size_t obj_size, 43 int prealloc_size) 44 { 45 struct lthread_objcache *c = 46 rte_malloc_socket(NULL, sizeof(struct lthread_objcache), 47 RTE_CACHE_LINE_SIZE, 48 rte_socket_id()); 49 if (c == NULL) 50 return NULL; 51 52 c->q = _lthread_queue_create("cache queue"); 53 if (c->q == NULL) { 54 rte_free(c); 55 return NULL; 56 } 57 c->obj_size = obj_size; 58 c->prealloc_size = prealloc_size; 59 60 if (name != NULL) 61 strncpy(c->name, name, LT_MAX_NAME_SIZE); 62 c->name[sizeof(c->name)-1] = 0; 63 64 DIAG_COUNT_INIT(c, rd); 65 DIAG_COUNT_INIT(c, wr); 66 DIAG_COUNT_INIT(c, prealloc); 67 DIAG_COUNT_INIT(c, capacity); 68 DIAG_COUNT_INIT(c, available); 69 return c; 70 } 71 72 /* 73 * Destroy an objcache 74 */ 75 static inline int 76 _lthread_objcache_destroy(struct lthread_objcache *c) 77 { 78 if (_lthread_queue_destroy(c->q) == 0) { 79 rte_free(c); 80 return 0; 81 } 82 return -1; 83 } 84 85 /* 86 * Allocate an object from an object cache 87 */ 88 static inline void * 89 _lthread_objcache_alloc(struct lthread_objcache *c) 90 { 91 int i; 92 void *data; 93 struct lthread_queue *q = c->q; 94 size_t obj_size = c->obj_size; 95 int prealloc_size = c->prealloc_size; 96 97 data = _lthread_queue_remove(q); 98 99 if (data == NULL) { 100 DIAG_COUNT_INC(c, prealloc); 101 for (i = 0; i < prealloc_size; i++) { 102 data = 103 rte_zmalloc_socket(NULL, obj_size, 104 RTE_CACHE_LINE_SIZE, 105 rte_socket_id()); 106 if (data == NULL) 107 return NULL; 108 109 DIAG_COUNT_INC(c, available); 110 DIAG_COUNT_INC(c, capacity); 111 _lthread_queue_insert_mp(q, data); 112 } 113 data = _lthread_queue_remove(q); 114 } 115 DIAG_COUNT_INC(c, rd); 116 DIAG_COUNT_DEC(c, available); 117 return data; 118 } 119 120 /* 121 * free an object to a cache 122 */ 123 static inline void 124 _lthread_objcache_free(struct lthread_objcache *c, void *obj) 125 { 126 DIAG_COUNT_INC(c, wr); 127 DIAG_COUNT_INC(c, available); 128 _lthread_queue_insert_mp(c->q, obj); 129 } 130 131 132 #ifdef __cplusplus 133 } 134 #endif 135 136 #endif /* LTHREAD_OBJCACHE_H_ */ 137