/* SPDX-License-Identifier: GPL-2.0-only */ #ifndef _MEM_POOL_H_ #define _MEM_POOL_H_ #include #include #include /* * The memory pool allows one to allocate memory from a fixed size buffer that * also allows freeing semantics for reuse. However, the current limitation is * that only the two most recent allocations can be freed (in exact reverse * order). If one tries to free any allocation that isn't at the top of the * allocation stack, or one allocates more than two buffers in a row without * freeing, it will result in a leak within the memory pool. (Two allocations * were chosen to optimize for the CBFS cache case which may need two buffers * to map a single compressed file, and will free them in reverse order.) * * You must ensure the backing buffer is 'alignment' aligned. */ struct mem_pool { uint8_t *buf; size_t size; size_t alignment; uint8_t *last_alloc; uint8_t *second_to_last_alloc; size_t free_offset; }; #define MEM_POOL_INIT(buf_, size_, alignment_) \ { \ .buf = (buf_), \ .size = (size_), \ .alignment = (alignment_), \ .last_alloc = NULL, \ .second_to_last_alloc = NULL, \ .free_offset = 0, \ } static inline void mem_pool_reset(struct mem_pool *mp) { mp->last_alloc = NULL; mp->second_to_last_alloc = NULL; mp->free_offset = 0; } /* Initialize a memory pool. */ static inline void mem_pool_init(struct mem_pool *mp, void *buf, size_t sz, size_t alignment) { assert(alignment); assert((uintptr_t)buf % alignment == 0); mp->buf = buf; mp->size = sz; mp->alignment = alignment; mem_pool_reset(mp); } /* Allocate requested size from the memory pool. NULL returned on error. */ void *mem_pool_alloc(struct mem_pool *mp, size_t sz); /* Free allocation from memory pool. */ void mem_pool_free(struct mem_pool *mp, void *alloc); #endif /* _MEM_POOL_H_ */