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