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