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
_lthread_objcache_create(const char * name,size_t obj_size,int prealloc_size)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
_lthread_objcache_destroy(struct lthread_objcache * c)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 *
_lthread_objcache_alloc(struct lthread_objcache * c)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
_lthread_objcache_free(struct lthread_objcache * c,void * obj)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