tle_memtank_pub.h revision 703faabf
1/*
2 * Copyright (c) 2019  Intel Corporation.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef _TLE_MEMTANK_PUB_H_
17#define _TLE_MEMTANK_PUB_H_
18
19#include <tle_memtank.h>
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25/**
26 * @file
27 * TLE memtank public
28 * It is not recommended to include this file directly,
29 * include <tle_memtank.h> instead.
30 */
31
32struct tle_memtank {
33	rte_spinlock_t lock;
34	uint32_t min_free;
35	uint32_t max_free;
36	uint32_t nb_free;
37	void *free[];
38} __rte_cache_aligned;
39
40
41static inline void
42_copy_objs(void *dst[], void * const src[], uint32_t num)
43{
44	uint32_t i, n;
45
46	n = RTE_ALIGN_FLOOR(num, 4);
47
48	for (i = 0; i != n; i += 4) {
49		dst[i] = src[i];
50		dst[i + 1] = src[i + 1];
51		dst[i + 2] = src[i + 2];
52		dst[i + 3] = src[i + 3];
53	}
54
55	switch (num % 4) {
56	case 3:
57		dst[i + 2] = src[i + 2];
58		/* fallthrough */
59	case 2:
60		dst[i + 1] = src[i + 1];
61		/* fallthrough */
62	case 1:
63		dst[i] = src[i];
64		/* fallthrough */
65	}
66}
67
68static inline uint32_t
69_get_free(struct tle_memtank *t, void *obj[], uint32_t num)
70{
71	uint32_t len, n;
72
73	rte_spinlock_lock(&t->lock);
74
75	len = t->nb_free;
76	n = RTE_MIN(num, len);
77	len -= n;
78	_copy_objs(obj, t->free + len, n);
79	t->nb_free = len;
80
81	rte_spinlock_unlock(&t->lock);
82	return n;
83}
84
85static inline uint32_t
86_put_free(struct tle_memtank *t, void * const obj[], uint32_t num)
87{
88	uint32_t len, n;
89
90	rte_spinlock_lock(&t->lock);
91
92	len = t->nb_free;
93	n = t->max_free - len;
94	n = RTE_MIN(num, n);
95	_copy_objs(t->free + len, obj, n);
96	t->nb_free = len + n;
97
98	rte_spinlock_unlock(&t->lock);
99	return n;
100}
101
102static inline void
103_fill_free(struct tle_memtank *t, uint32_t num, uint32_t flags)
104{
105	uint32_t k, n;
106	void *free[num];
107
108	k = tle_memtank_chunk_alloc(t, free, RTE_DIM(free), flags);
109	n = _put_free(t, free, k);
110	if (n != k)
111		tle_memtank_chunk_free(t, free + n, k - n, 0);
112}
113
114static inline uint32_t
115tle_memtank_alloc(struct tle_memtank *t, void *obj[], uint32_t num,
116	uint32_t flags)
117{
118	uint32_t n;
119
120	n = _get_free(t, obj, num);
121
122	/* not enough free objects, try to allocate via memchunks */
123	if (n != num && flags != 0) {
124		n += tle_memtank_chunk_alloc(t, obj + n, num - n, flags);
125
126		/* refill *free* tank */
127		if (n == num)
128			_fill_free(t, t->min_free, flags);
129	}
130
131	return n;
132}
133
134static inline void
135tle_memtank_free(struct tle_memtank *t, void * const obj[], uint32_t num,
136	uint32_t flags)
137{
138	uint32_t n;
139
140	n = _put_free(t, obj, num);
141	if (n != num)
142		tle_memtank_chunk_free(t, obj + n, num - n, flags);
143}
144
145#ifdef __cplusplus
146}
147#endif
148
149#endif /* _TLE_MEMTANK_PUB_H_ */
150