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