1*2bfe3f2eSlogwang /*-
2*2bfe3f2eSlogwang  *   BSD LICENSE
3*2bfe3f2eSlogwang  *
4*2bfe3f2eSlogwang  *   Copyright(c) 2016 Intel Corporation. All rights reserved.
5*2bfe3f2eSlogwang  *   All rights reserved.
6*2bfe3f2eSlogwang  *
7*2bfe3f2eSlogwang  *   Redistribution and use in source and binary forms, with or without
8*2bfe3f2eSlogwang  *   modification, are permitted provided that the following conditions
9*2bfe3f2eSlogwang  *   are met:
10*2bfe3f2eSlogwang  *
11*2bfe3f2eSlogwang  *     * Redistributions of source code must retain the above copyright
12*2bfe3f2eSlogwang  *       notice, this list of conditions and the following disclaimer.
13*2bfe3f2eSlogwang  *     * Redistributions in binary form must reproduce the above copyright
14*2bfe3f2eSlogwang  *       notice, this list of conditions and the following disclaimer in
15*2bfe3f2eSlogwang  *       the documentation and/or other materials provided with the
16*2bfe3f2eSlogwang  *       distribution.
17*2bfe3f2eSlogwang  *     * Neither the name of Intel Corporation nor the names of its
18*2bfe3f2eSlogwang  *       contributors may be used to endorse or promote products derived
19*2bfe3f2eSlogwang  *       from this software without specific prior written permission.
20*2bfe3f2eSlogwang  *
21*2bfe3f2eSlogwang  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*2bfe3f2eSlogwang  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*2bfe3f2eSlogwang  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*2bfe3f2eSlogwang  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25*2bfe3f2eSlogwang  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*2bfe3f2eSlogwang  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27*2bfe3f2eSlogwang  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*2bfe3f2eSlogwang  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29*2bfe3f2eSlogwang  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30*2bfe3f2eSlogwang  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*2bfe3f2eSlogwang  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*2bfe3f2eSlogwang  */
33*2bfe3f2eSlogwang 
34*2bfe3f2eSlogwang #include <stdio.h>
35*2bfe3f2eSlogwang #include <rte_mempool.h>
36*2bfe3f2eSlogwang #include <rte_malloc.h>
37*2bfe3f2eSlogwang 
38*2bfe3f2eSlogwang struct rte_mempool_stack {
39*2bfe3f2eSlogwang 	rte_spinlock_t sl;
40*2bfe3f2eSlogwang 
41*2bfe3f2eSlogwang 	uint32_t size;
42*2bfe3f2eSlogwang 	uint32_t len;
43*2bfe3f2eSlogwang 	void *objs[];
44*2bfe3f2eSlogwang };
45*2bfe3f2eSlogwang 
46*2bfe3f2eSlogwang static int
47*2bfe3f2eSlogwang stack_alloc(struct rte_mempool *mp)
48*2bfe3f2eSlogwang {
49*2bfe3f2eSlogwang 	struct rte_mempool_stack *s;
50*2bfe3f2eSlogwang 	unsigned n = mp->size;
51*2bfe3f2eSlogwang 	int size = sizeof(*s) + (n+16)*sizeof(void *);
52*2bfe3f2eSlogwang 
53*2bfe3f2eSlogwang 	/* Allocate our local memory structure */
54*2bfe3f2eSlogwang 	s = rte_zmalloc_socket("mempool-stack",
55*2bfe3f2eSlogwang 			size,
56*2bfe3f2eSlogwang 			RTE_CACHE_LINE_SIZE,
57*2bfe3f2eSlogwang 			mp->socket_id);
58*2bfe3f2eSlogwang 	if (s == NULL) {
59*2bfe3f2eSlogwang 		RTE_LOG(ERR, MEMPOOL, "Cannot allocate stack!\n");
60*2bfe3f2eSlogwang 		return -ENOMEM;
61*2bfe3f2eSlogwang 	}
62*2bfe3f2eSlogwang 
63*2bfe3f2eSlogwang 	rte_spinlock_init(&s->sl);
64*2bfe3f2eSlogwang 
65*2bfe3f2eSlogwang 	s->size = n;
66*2bfe3f2eSlogwang 	mp->pool_data = s;
67*2bfe3f2eSlogwang 
68*2bfe3f2eSlogwang 	return 0;
69*2bfe3f2eSlogwang }
70*2bfe3f2eSlogwang 
71*2bfe3f2eSlogwang static int
72*2bfe3f2eSlogwang stack_enqueue(struct rte_mempool *mp, void * const *obj_table,
73*2bfe3f2eSlogwang 		unsigned n)
74*2bfe3f2eSlogwang {
75*2bfe3f2eSlogwang 	struct rte_mempool_stack *s = mp->pool_data;
76*2bfe3f2eSlogwang 	void **cache_objs;
77*2bfe3f2eSlogwang 	unsigned index;
78*2bfe3f2eSlogwang 
79*2bfe3f2eSlogwang 	rte_spinlock_lock(&s->sl);
80*2bfe3f2eSlogwang 	cache_objs = &s->objs[s->len];
81*2bfe3f2eSlogwang 
82*2bfe3f2eSlogwang 	/* Is there sufficient space in the stack ? */
83*2bfe3f2eSlogwang 	if ((s->len + n) > s->size) {
84*2bfe3f2eSlogwang 		rte_spinlock_unlock(&s->sl);
85*2bfe3f2eSlogwang 		return -ENOBUFS;
86*2bfe3f2eSlogwang 	}
87*2bfe3f2eSlogwang 
88*2bfe3f2eSlogwang 	/* Add elements back into the cache */
89*2bfe3f2eSlogwang 	for (index = 0; index < n; ++index, obj_table++)
90*2bfe3f2eSlogwang 		cache_objs[index] = *obj_table;
91*2bfe3f2eSlogwang 
92*2bfe3f2eSlogwang 	s->len += n;
93*2bfe3f2eSlogwang 
94*2bfe3f2eSlogwang 	rte_spinlock_unlock(&s->sl);
95*2bfe3f2eSlogwang 	return 0;
96*2bfe3f2eSlogwang }
97*2bfe3f2eSlogwang 
98*2bfe3f2eSlogwang static int
99*2bfe3f2eSlogwang stack_dequeue(struct rte_mempool *mp, void **obj_table,
100*2bfe3f2eSlogwang 		unsigned n)
101*2bfe3f2eSlogwang {
102*2bfe3f2eSlogwang 	struct rte_mempool_stack *s = mp->pool_data;
103*2bfe3f2eSlogwang 	void **cache_objs;
104*2bfe3f2eSlogwang 	unsigned index, len;
105*2bfe3f2eSlogwang 
106*2bfe3f2eSlogwang 	rte_spinlock_lock(&s->sl);
107*2bfe3f2eSlogwang 
108*2bfe3f2eSlogwang 	if (unlikely(n > s->len)) {
109*2bfe3f2eSlogwang 		rte_spinlock_unlock(&s->sl);
110*2bfe3f2eSlogwang 		return -ENOENT;
111*2bfe3f2eSlogwang 	}
112*2bfe3f2eSlogwang 
113*2bfe3f2eSlogwang 	cache_objs = s->objs;
114*2bfe3f2eSlogwang 
115*2bfe3f2eSlogwang 	for (index = 0, len = s->len - 1; index < n;
116*2bfe3f2eSlogwang 			++index, len--, obj_table++)
117*2bfe3f2eSlogwang 		*obj_table = cache_objs[len];
118*2bfe3f2eSlogwang 
119*2bfe3f2eSlogwang 	s->len -= n;
120*2bfe3f2eSlogwang 	rte_spinlock_unlock(&s->sl);
121*2bfe3f2eSlogwang 	return 0;
122*2bfe3f2eSlogwang }
123*2bfe3f2eSlogwang 
124*2bfe3f2eSlogwang static unsigned
125*2bfe3f2eSlogwang stack_get_count(const struct rte_mempool *mp)
126*2bfe3f2eSlogwang {
127*2bfe3f2eSlogwang 	struct rte_mempool_stack *s = mp->pool_data;
128*2bfe3f2eSlogwang 
129*2bfe3f2eSlogwang 	return s->len;
130*2bfe3f2eSlogwang }
131*2bfe3f2eSlogwang 
132*2bfe3f2eSlogwang static void
133*2bfe3f2eSlogwang stack_free(struct rte_mempool *mp)
134*2bfe3f2eSlogwang {
135*2bfe3f2eSlogwang 	rte_free((void *)(mp->pool_data));
136*2bfe3f2eSlogwang }
137*2bfe3f2eSlogwang 
138*2bfe3f2eSlogwang static struct rte_mempool_ops ops_stack = {
139*2bfe3f2eSlogwang 	.name = "stack",
140*2bfe3f2eSlogwang 	.alloc = stack_alloc,
141*2bfe3f2eSlogwang 	.free = stack_free,
142*2bfe3f2eSlogwang 	.enqueue = stack_enqueue,
143*2bfe3f2eSlogwang 	.dequeue = stack_dequeue,
144*2bfe3f2eSlogwang 	.get_count = stack_get_count
145*2bfe3f2eSlogwang };
146*2bfe3f2eSlogwang 
147*2bfe3f2eSlogwang MEMPOOL_REGISTER_OPS(ops_stack);
148