aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libtle_memtank/tle_memtank.h
blob: 9f12fe09994d409eab9c5e996a5c5c05769bc24b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*
 * Copyright (c) 2019  Intel Corporation.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _TLE_MEMTANK_H_
#define _TLE_MEMTANK_H_

#include <string.h>

#include <rte_common.h>
#include <rte_memory.h>
#include <rte_atomic.h>
#include <rte_spinlock.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @file
 * TLE memtank
 *
 * Same a s mempool it allows to alloc/free objects of fixed size
 * in a lightweight manner (probably not as lightweight as mempool,
 * but hopefully close enough).
 * But in addition it can grow/shrink dynamically plus provides extra
 * additional API for higher flexibility:
 *	- manual grow()/shrink() functions
 *	- different alloc/free policies
 *        (can be specified by user via flags parameter).
 * Internally it consists of:
 *	- LIFO queue (fast allocator/deallocator)
 *	- lists of memchunks (USED, FREE).
 *
 * For perfomance reasons memtank tries to allocate memory in
 * relatively big chunks (memchunks) and then split each memchunk
 * in dozens (or hundreds) of objects.
 * There are two thresholds:
 *	- min_free (grow threshold)
 *	- max_free (shrink threshold)
 */

struct tle_memtank;

/** generic memtank behavior flags */
enum {
	TLE_MTANK_OBJ_DBG = 1,
};

struct tle_memtank_prm {
	/** min number of free objs in the ring (grow threshold). */
	uint32_t min_free;
	uint32_t max_free;  /**< max number of free objs (empty threshold) */
	uint32_t max_obj; /**< max number of objs (grow limit) */
	uint32_t obj_size;  /**< size of each mem object */
	uint32_t obj_align;  /**< alignment of each mem object */
	uint32_t nb_obj_chunk; /**< number of objects per chunk */
	uint32_t flags; /**< behavior flags */
	/** user provided function to alloc chunk of memory */
	void * (*alloc)(size_t, void *);
	/** user provided function to free chunk of memory */
	void (*free)(void *, void *);
	/** user provided function to initialiaze an object */
	void (*init)(void *[], uint32_t, void *);
	void *udata;        /**< opaque user data for alloc/free/init */
};

/**
 * Allocate and intitialize new memtank instance, based on the
 * parameters provided. Note that it uses user-provided *alloc()* function
 * to allocate space for the memtank metadata.
 * @param prm
 *   Parameters used to create and initialise new memtank.
 * @return
 *   - Pointer to new memtank insteance created, if operation completed
 *     successfully.
 *   - NULL on error with rte_errno set appropriately.
 */
struct tle_memtank *
tle_memtank_create(const struct tle_memtank_prm *prm);

/**
 * Destroy the memtank and free all memory referenced by the memtank.
 * The objects must not be used by other cores as they will be freed.
 *
 * @param t
 *   A pointer to the memtank instance.
 */
void
tle_memtank_destroy(struct tle_memtank *t);


/** alloc flags */
enum {
	TLE_MTANK_ALLOC_CHUNK = 1,
	TLE_MTANK_ALLOC_GROW = 2,
};

/**
 * Allocate up to requested number of objects from the memtank.
 * Note that depending on *alloc* behavior (flags) some new memory chunks
 * can be allocated from the underlying memory subsystem.
 *
 * @param t
 *   A pointer to the memtank instance.
 * @param obj
 *   An array of void * pointers (objects) that will be filled.
 * @param num
 *   Number of objects to allocate from the memtank.
 * @param flags
 *   Flags that control allocation behavior.
 * @return
 *   Number of allocated objects.
 */
static inline uint32_t
tle_memtank_alloc(struct tle_memtank *t, void *obj[], uint32_t num,
		uint32_t flags);

/**
 * Allocate up to requested number of objects from the memtank.
 * Note that this function bypasses *free* cache(s) and tries to allocate
 * objects straight from the memory chunks.
 * Note that depending on *alloc* behavior (flags) some new memory chunks
 * can be allocated from the underlying memory subsystem.
 *
 * @param t
 *   A pointer to the memtank instance.
 * @param obj
 *   An array of void * pointers (objects) that will be filled.
 * @param nb_obj
 *   Number of objects to allocate from the memtank.
 * @param flags
 *   Flags that control allocation behavior.
 * @return
 *   Number of allocated objects.
 */
uint32_t
tle_memtank_chunk_alloc(struct tle_memtank *t, void *obj[], uint32_t nb_obj,
		uint32_t flags);

/** free flags */
enum {
	TLE_MTANK_FREE_SHRINK = 1,
};

/**
 * Free (put) provided objects back to the memtank.
 * Note that depending on *free* behavior (flags) some memory chunks can be
 * returned (freed) to the underlying memory subsystem.
 *
 * @param t
 *   A pointer to the memtank instance.
 * @param obj
 *   An array of object pointers to be freed.
 * @param num
 *   Number of objects to free.
 * @param flags
 *   Flags that control free behavior.
 */
static inline void
tle_memtank_free(struct tle_memtank *t, void * const obj[],  uint32_t num,
		uint32_t flags);

/**
 * Free (put) provided objects back to the memtank.
 * Note that this function bypasses *free* cache(s) and tries to put
 * objects straight to the memory chunks.
 * Note that depending on *free* behavior (flags) some memory chunks can be
 * returned (freed) to the underlying memory subsystem.
 *
 * @param t
 *   A pointer to the memtank instance.
 * @param obj
 *   An array of object pointers to be freed.
 * @param nb_obj
 *   Number of objects to allocate from the memtank.
 * @param flags
 *   Flags that control allocation behavior.
 */
void
tle_memtank_chunk_free(struct tle_memtank *t, void * const obj[],
		uint32_t nb_obj, uint32_t flags);

/**
 * Check does number of objects in *free* cache is below memtank grow
 * threshold (min_free). If yes, then tries to allocate memory for new
 * objects from the underlying memory subsystem.
 *
 * @param t
 *   A pointer to the memtank instance.
 * @return
 *   Number of newly allocated memory chunks.
 */
int
tle_memtank_grow(struct tle_memtank *t);

/**
 * Check does number of objects in *free* cache have reached memtank shrink
 * threshold (max_free). If yes, then tries to return excessive memory to
 * the the underlying memory subsystem.
 *
 * @param t
 *   A pointer to the memtank instance.
 * @return
 *   Number of freed memory chunks.
 */
int
tle_memtank_shrink(struct tle_memtank *t);

/* dump flags */
enum {
	TLE_MTANK_DUMP_FREE_STAT = 1,
	TLE_MTANK_DUMP_CHUNK_STAT = 2,
	TLE_MTANK_DUMP_CHUNK = 4,
	/* first not used power of two */
	TLE_MTANK_DUMP_END,

	/* dump all stats */
	TLE_MTANK_DUMP_STAT =
		(TLE_MTANK_DUMP_FREE_STAT | TLE_MTANK_DUMP_CHUNK_STAT),
	/* dump everything */
	TLE_MTANK_DUMP_ALL = TLE_MTANK_DUMP_END - 1,
};

/**
 * Dump information about the memtank to the file.
 * Note that depending of *flags* value it might cause some internal locks
 * grabbing, and might affect perfomance of others threads that
 * concurently use same memtank.
 *
 * @param f
 *   A pinter to the file.
 * @param t
 *   A pointer to the memtank instance.
 * @param flags
 *   Flags that control dump behavior.
 */
void
tle_memtank_dump(FILE *f, const struct tle_memtank *t, uint32_t flags);

/**
 * Check the consistency of the given memtank instance.
 * Dumps error messages to the RTE log subsystem, if some inconsitency
 * is detected.
 *
 * @param t
 *   A pointer to the memtank instance.
 * @param ct
 *   Value greater then zero, if some other threads do concurently use
 *   that memtank.
 * @return
 *   Zero on success, or negaive value otherwise.
 */
int
tle_memtank_sanity_check(const struct tle_memtank *t, int32_t ct);

#ifdef __cplusplus
}
#endif

#include <tle_memtank_pub.h>

#endif /* _TLE_MEMTANK_H_ */