diff options
author | Konstantin Ananyev <konstantin.ananyev@intel.com> | 2019-06-27 19:28:26 +0100 |
---|---|---|
committer | Konstantin Ananyev <konstantin.ananyev@intel.com> | 2019-12-31 11:42:11 +0000 |
commit | 703faabf2d44d245fe1dd0b75f1736bf6114a557 (patch) | |
tree | 1695eb924b9ff8236e0eabb084ab6b969c162d88 /lib/libtle_memtank/tle_memtank_pub.h | |
parent | 0ee0943991b7d2cb43c63c76ba59035cacbc1b91 (diff) |
v6: memtank introduction
For analogy with mempool, named this structure memtank.
Same a s mempool it allows to alloc/free objects of fixed size
in a lightweight manner (not as lightweight as mempool,
but hopefully close enough).
The whole idea is that alloc/free is used at fast-path and don't
allocate/free more than *min_free* objects at one call.
So for majority of cases our fast-path alloc/free should be lightweight
(LIFO enqueue/dequeue operations).
Also user will need to call grow/shrink periodically
(ideally from the slow-path) to make sure there is enough
free objects in the tank.
Internally it is just a simple LIFO for up to *max_free* objects plus
a list of memory buffers (memchunk) from where these objects were
allocated.
v1 -> v2
- Added UT
- Fixed few bugs
v2 -> v3
- extend UT with more parameters
v3 -> v4
- add object alignement as parameter for memtank_create
- extend UT with more parameters
- added memtank dump routine
v4 -> v5
- fixed few bugs inside memtank lib
- extend UT with:
- new test case
- new command-line options: '-s <obj_size>', '-m <mem_func>'
v5 -> v6
- extend memtank dump to collect/display extra information
- make memtank dump routine MT safe
- add memtank sanity check function
- add proper comments for pubic API
Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Change-Id: I8939772577f5d9e293088eaa9a9fe316c3fe8f87
Diffstat (limited to 'lib/libtle_memtank/tle_memtank_pub.h')
-rw-r--r-- | lib/libtle_memtank/tle_memtank_pub.h | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/lib/libtle_memtank/tle_memtank_pub.h b/lib/libtle_memtank/tle_memtank_pub.h new file mode 100644 index 0000000..78e89b2 --- /dev/null +++ b/lib/libtle_memtank/tle_memtank_pub.h @@ -0,0 +1,149 @@ +/* + * 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_PUB_H_ +#define _TLE_MEMTANK_PUB_H_ + +#include <tle_memtank.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * TLE memtank public + * It is not recommended to include this file directly, + * include <tle_memtank.h> instead. + */ + +struct tle_memtank { + rte_spinlock_t lock; + uint32_t min_free; + uint32_t max_free; + uint32_t nb_free; + void *free[]; +} __rte_cache_aligned; + + +static inline void +_copy_objs(void *dst[], void * const src[], uint32_t num) +{ + uint32_t i, n; + + n = RTE_ALIGN_FLOOR(num, 4); + + for (i = 0; i != n; i += 4) { + dst[i] = src[i]; + dst[i + 1] = src[i + 1]; + dst[i + 2] = src[i + 2]; + dst[i + 3] = src[i + 3]; + } + + switch (num % 4) { + case 3: + dst[i + 2] = src[i + 2]; + /* fallthrough */ + case 2: + dst[i + 1] = src[i + 1]; + /* fallthrough */ + case 1: + dst[i] = src[i]; + /* fallthrough */ + } +} + +static inline uint32_t +_get_free(struct tle_memtank *t, void *obj[], uint32_t num) +{ + uint32_t len, n; + + rte_spinlock_lock(&t->lock); + + len = t->nb_free; + n = RTE_MIN(num, len); + len -= n; + _copy_objs(obj, t->free + len, n); + t->nb_free = len; + + rte_spinlock_unlock(&t->lock); + return n; +} + +static inline uint32_t +_put_free(struct tle_memtank *t, void * const obj[], uint32_t num) +{ + uint32_t len, n; + + rte_spinlock_lock(&t->lock); + + len = t->nb_free; + n = t->max_free - len; + n = RTE_MIN(num, n); + _copy_objs(t->free + len, obj, n); + t->nb_free = len + n; + + rte_spinlock_unlock(&t->lock); + return n; +} + +static inline void +_fill_free(struct tle_memtank *t, uint32_t num, uint32_t flags) +{ + uint32_t k, n; + void *free[num]; + + k = tle_memtank_chunk_alloc(t, free, RTE_DIM(free), flags); + n = _put_free(t, free, k); + if (n != k) + tle_memtank_chunk_free(t, free + n, k - n, 0); +} + +static inline uint32_t +tle_memtank_alloc(struct tle_memtank *t, void *obj[], uint32_t num, + uint32_t flags) +{ + uint32_t n; + + n = _get_free(t, obj, num); + + /* not enough free objects, try to allocate via memchunks */ + if (n != num && flags != 0) { + n += tle_memtank_chunk_alloc(t, obj + n, num - n, flags); + + /* refill *free* tank */ + if (n == num) + _fill_free(t, t->min_free, flags); + } + + return n; +} + +static inline void +tle_memtank_free(struct tle_memtank *t, void * const obj[], uint32_t num, + uint32_t flags) +{ + uint32_t n; + + n = _put_free(t, obj, num); + if (n != num) + tle_memtank_chunk_free(t, obj + n, num - n, flags); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _TLE_MEMTANK_PUB_H_ */ |