1a9643ea8Slogwang /*-
2a9643ea8Slogwang  *   BSD LICENSE
3a9643ea8Slogwang  *
4a9643ea8Slogwang  *   Copyright(c) 2015 Intel Corporation. All rights reserved.
5a9643ea8Slogwang  *   All rights reserved.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  *   Redistribution and use in source and binary forms, with or without
8a9643ea8Slogwang  *   modification, are permitted provided that the following conditions
9a9643ea8Slogwang  *   are met:
10a9643ea8Slogwang  *
11a9643ea8Slogwang  *     * Redistributions of source code must retain the above copyright
12a9643ea8Slogwang  *       notice, this list of conditions and the following disclaimer.
13a9643ea8Slogwang  *     * Redistributions in binary form must reproduce the above copyright
14a9643ea8Slogwang  *       notice, this list of conditions and the following disclaimer in
15a9643ea8Slogwang  *       the documentation and/or other materials provided with the
16a9643ea8Slogwang  *       distribution.
17a9643ea8Slogwang  *     * Neither the name of Intel Corporation nor the names of its
18a9643ea8Slogwang  *       contributors may be used to endorse or promote products derived
19a9643ea8Slogwang  *       from this software without specific prior written permission.
20a9643ea8Slogwang  *
21a9643ea8Slogwang  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22a9643ea8Slogwang  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23a9643ea8Slogwang  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24a9643ea8Slogwang  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25a9643ea8Slogwang  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26a9643ea8Slogwang  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27a9643ea8Slogwang  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28a9643ea8Slogwang  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29a9643ea8Slogwang  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30a9643ea8Slogwang  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31a9643ea8Slogwang  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32a9643ea8Slogwang  */
33a9643ea8Slogwang #ifndef LTHREAD_OBJCACHE_H_
34a9643ea8Slogwang #define LTHREAD_OBJCACHE_H_
35a9643ea8Slogwang 
36*2bfe3f2eSlogwang #ifdef __cplusplus
37*2bfe3f2eSlogwang extern "C" {
38*2bfe3f2eSlogwang #endif
39*2bfe3f2eSlogwang 
40a9643ea8Slogwang #include <string.h>
41a9643ea8Slogwang 
42a9643ea8Slogwang #include <rte_per_lcore.h>
43a9643ea8Slogwang #include <rte_malloc.h>
44a9643ea8Slogwang #include <rte_memory.h>
45a9643ea8Slogwang 
46a9643ea8Slogwang #include "lthread_int.h"
47a9643ea8Slogwang #include "lthread_diag.h"
48a9643ea8Slogwang #include "lthread_queue.h"
49a9643ea8Slogwang 
50a9643ea8Slogwang 
51a9643ea8Slogwang RTE_DECLARE_PER_LCORE(struct lthread_sched *, this_sched);
52a9643ea8Slogwang 
53a9643ea8Slogwang struct lthread_objcache {
54a9643ea8Slogwang 	struct lthread_queue *q;
55a9643ea8Slogwang 	size_t obj_size;
56a9643ea8Slogwang 	int prealloc_size;
57a9643ea8Slogwang 	char name[LT_MAX_NAME_SIZE];
58a9643ea8Slogwang 
59a9643ea8Slogwang 	DIAG_COUNT_DEFINE(rd);
60a9643ea8Slogwang 	DIAG_COUNT_DEFINE(wr);
61a9643ea8Slogwang 	DIAG_COUNT_DEFINE(prealloc);
62a9643ea8Slogwang 	DIAG_COUNT_DEFINE(capacity);
63a9643ea8Slogwang 	DIAG_COUNT_DEFINE(available);
64a9643ea8Slogwang };
65a9643ea8Slogwang 
66a9643ea8Slogwang /*
67a9643ea8Slogwang  * Create a cache
68a9643ea8Slogwang  */
69a9643ea8Slogwang static inline struct
70a9643ea8Slogwang lthread_objcache *_lthread_objcache_create(const char *name,
71a9643ea8Slogwang 					size_t obj_size,
72a9643ea8Slogwang 					int prealloc_size)
73a9643ea8Slogwang {
74a9643ea8Slogwang 	struct lthread_objcache *c =
75a9643ea8Slogwang 	    rte_malloc_socket(NULL, sizeof(struct lthread_objcache),
76a9643ea8Slogwang 				RTE_CACHE_LINE_SIZE,
77a9643ea8Slogwang 				rte_socket_id());
78a9643ea8Slogwang 	if (c == NULL)
79a9643ea8Slogwang 		return NULL;
80a9643ea8Slogwang 
81a9643ea8Slogwang 	c->q = _lthread_queue_create("cache queue");
82a9643ea8Slogwang 	if (c->q == NULL) {
83a9643ea8Slogwang 		rte_free(c);
84a9643ea8Slogwang 		return NULL;
85a9643ea8Slogwang 	}
86a9643ea8Slogwang 	c->obj_size = obj_size;
87a9643ea8Slogwang 	c->prealloc_size = prealloc_size;
88a9643ea8Slogwang 
89a9643ea8Slogwang 	if (name != NULL)
90a9643ea8Slogwang 		strncpy(c->name, name, LT_MAX_NAME_SIZE);
91a9643ea8Slogwang 	c->name[sizeof(c->name)-1] = 0;
92a9643ea8Slogwang 
93a9643ea8Slogwang 	DIAG_COUNT_INIT(c, rd);
94a9643ea8Slogwang 	DIAG_COUNT_INIT(c, wr);
95a9643ea8Slogwang 	DIAG_COUNT_INIT(c, prealloc);
96a9643ea8Slogwang 	DIAG_COUNT_INIT(c, capacity);
97a9643ea8Slogwang 	DIAG_COUNT_INIT(c, available);
98a9643ea8Slogwang 	return c;
99a9643ea8Slogwang }
100a9643ea8Slogwang 
101a9643ea8Slogwang /*
102a9643ea8Slogwang  * Destroy an objcache
103a9643ea8Slogwang  */
104a9643ea8Slogwang static inline int
105a9643ea8Slogwang _lthread_objcache_destroy(struct lthread_objcache *c)
106a9643ea8Slogwang {
107a9643ea8Slogwang 	if (_lthread_queue_destroy(c->q) == 0) {
108a9643ea8Slogwang 		rte_free(c);
109a9643ea8Slogwang 		return 0;
110a9643ea8Slogwang 	}
111a9643ea8Slogwang 	return -1;
112a9643ea8Slogwang }
113a9643ea8Slogwang 
114a9643ea8Slogwang /*
115a9643ea8Slogwang  * Allocate an object from an object cache
116a9643ea8Slogwang  */
117a9643ea8Slogwang static inline void *
118a9643ea8Slogwang _lthread_objcache_alloc(struct lthread_objcache *c)
119a9643ea8Slogwang {
120a9643ea8Slogwang 	int i;
121a9643ea8Slogwang 	void *data;
122a9643ea8Slogwang 	struct lthread_queue *q = c->q;
123a9643ea8Slogwang 	size_t obj_size = c->obj_size;
124a9643ea8Slogwang 	int prealloc_size = c->prealloc_size;
125a9643ea8Slogwang 
126a9643ea8Slogwang 	data = _lthread_queue_remove(q);
127a9643ea8Slogwang 
128a9643ea8Slogwang 	if (data == NULL) {
129a9643ea8Slogwang 		DIAG_COUNT_INC(c, prealloc);
130a9643ea8Slogwang 		for (i = 0; i < prealloc_size; i++) {
131a9643ea8Slogwang 			data =
132a9643ea8Slogwang 			    rte_zmalloc_socket(NULL, obj_size,
133a9643ea8Slogwang 					RTE_CACHE_LINE_SIZE,
134a9643ea8Slogwang 					rte_socket_id());
135a9643ea8Slogwang 			if (data == NULL)
136a9643ea8Slogwang 				return NULL;
137a9643ea8Slogwang 
138a9643ea8Slogwang 			DIAG_COUNT_INC(c, available);
139a9643ea8Slogwang 			DIAG_COUNT_INC(c, capacity);
140a9643ea8Slogwang 			_lthread_queue_insert_mp(q, data);
141a9643ea8Slogwang 		}
142a9643ea8Slogwang 		data = _lthread_queue_remove(q);
143a9643ea8Slogwang 	}
144a9643ea8Slogwang 	DIAG_COUNT_INC(c, rd);
145a9643ea8Slogwang 	DIAG_COUNT_DEC(c, available);
146a9643ea8Slogwang 	return data;
147a9643ea8Slogwang }
148a9643ea8Slogwang 
149a9643ea8Slogwang /*
150a9643ea8Slogwang  * free an object to a cache
151a9643ea8Slogwang  */
152a9643ea8Slogwang static inline void
153a9643ea8Slogwang _lthread_objcache_free(struct lthread_objcache *c, void *obj)
154a9643ea8Slogwang {
155a9643ea8Slogwang 	DIAG_COUNT_INC(c, wr);
156a9643ea8Slogwang 	DIAG_COUNT_INC(c, available);
157a9643ea8Slogwang 	_lthread_queue_insert_mp(c->q, obj);
158a9643ea8Slogwang }
159a9643ea8Slogwang 
160a9643ea8Slogwang 
161*2bfe3f2eSlogwang #ifdef __cplusplus
162*2bfe3f2eSlogwang }
163*2bfe3f2eSlogwang #endif
164a9643ea8Slogwang 
165a9643ea8Slogwang #endif				/* LTHREAD_OBJCACHE_H_ */
166