1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #ifndef _MEM_POOL_H_
4 #define _MEM_POOL_H_
5
6 #include <assert.h>
7 #include <stddef.h>
8 #include <stdint.h>
9
10 /*
11 * The memory pool allows one to allocate memory from a fixed size buffer that
12 * also allows freeing semantics for reuse. However, the current limitation is
13 * that only the two most recent allocations can be freed (in exact reverse
14 * order). If one tries to free any allocation that isn't at the top of the
15 * allocation stack, or one allocates more than two buffers in a row without
16 * freeing, it will result in a leak within the memory pool. (Two allocations
17 * were chosen to optimize for the CBFS cache case which may need two buffers
18 * to map a single compressed file, and will free them in reverse order.)
19 *
20 * You must ensure the backing buffer is 'alignment' aligned.
21 */
22
23 struct mem_pool {
24 uint8_t *buf;
25 size_t size;
26 size_t alignment;
27 uint8_t *last_alloc;
28 uint8_t *second_to_last_alloc;
29 size_t free_offset;
30 };
31
32 #define MEM_POOL_INIT(buf_, size_, alignment_) \
33 { \
34 .buf = (buf_), \
35 .size = (size_), \
36 .alignment = (alignment_), \
37 .last_alloc = NULL, \
38 .second_to_last_alloc = NULL, \
39 .free_offset = 0, \
40 }
41
mem_pool_reset(struct mem_pool * mp)42 static inline void mem_pool_reset(struct mem_pool *mp)
43 {
44 mp->last_alloc = NULL;
45 mp->second_to_last_alloc = NULL;
46 mp->free_offset = 0;
47 }
48
49 /* Initialize a memory pool. */
mem_pool_init(struct mem_pool * mp,void * buf,size_t sz,size_t alignment)50 static inline void mem_pool_init(struct mem_pool *mp, void *buf, size_t sz,
51 size_t alignment)
52 {
53 assert(alignment);
54 assert((uintptr_t)buf % alignment == 0);
55
56 mp->buf = buf;
57 mp->size = sz;
58 mp->alignment = alignment;
59 mem_pool_reset(mp);
60 }
61
62 /* Allocate requested size from the memory pool. NULL returned on error. */
63 void *mem_pool_alloc(struct mem_pool *mp, size_t sz);
64
65 /* Free allocation from memory pool. */
66 void mem_pool_free(struct mem_pool *mp, void *alloc);
67
68 #endif /* _MEM_POOL_H_ */
69