blob: 42b5d1ed96b6599960f1b9686d4002ef153db033 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _MEM_POOL_H_
#define _MEM_POOL_H_
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
/*
* 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_ */