1 /*
2  *	UCW Library -- Memory Pools
3  *
4  *	(c) 1997--2005 Martin Mares <mj@ucw.cz>
5  *	(c) 2007 Pavel Charvat <pchar@ucw.cz>
6  *	(c) 2015, 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
7  *
8  *	This software may be freely distributed and used according to the terms
9  *	of the GNU Lesser General Public License.
10  */
11 
12 #pragma once
13 
14 #include <string.h>
15 #include <stdint.h>
16 
17 #define CPU_STRUCT_ALIGN (sizeof(void*))
18 
19 /***
20  * [[defs]]
21  * Definitions
22  * -----------
23  ***/
24 
25 /**
26  * Memory pool state (see mp_push(), ...).
27  * You should use this one as an opaque handle only, the insides are internal.
28  **/
29 struct mempool_state {
30 	unsigned free[2];
31 	void *last[2];
32 };
33 
34 /**
35  * Memory pool.
36  * You should use this one as an opaque handle only, the insides are internal.
37  **/
38 struct mempool {
39 	struct mempool_state state;
40 	void *unused, *last_big;
41 	unsigned chunk_size, threshold, idx;
42 };
43 
44 struct mempool_stats {			/** Mempool statistics. See mp_stats(). **/
45 	uint64_t total_size;		/** Real allocated size in bytes. */
46 	unsigned chain_count[3];	/** Number of allocated chunks in small/big/unused chains. */
47 	unsigned chain_size[3];		/** Size of allocated chunks in small/big/unused chains. */
48 };
49 
50 /***
51  * [[basic]]
52  * Basic manipulation
53  * ------------------
54  ***/
55 
56 /**
57  * Initialize a given mempool structure.
58  * \p chunk_size must be in the interval `[1, UINT_MAX / 2]`.
59  * It will allocate memory by this large chunks and take
60  * memory to satisfy requests from them.
61  *
62  * Memory pools can be treated as <<trans:respools,resources>>, see <<trans:res_mempool()>>.
63  **/
64 void mp_init(struct mempool *pool, unsigned chunk_size);
65 
66 /**
67  * Allocate and initialize a new memory pool.
68  * See \ref mp_init() for \p chunk_size limitations.
69  *
70  * The new mempool structure is allocated on the new mempool.
71  *
72  * Memory pools can be treated as <<trans:respools,resources>>, see <<trans:res_mempool()>>.
73  **/
74 struct mempool *mp_new(unsigned chunk_size);
75 
76 /**
77  * Cleanup mempool initialized by mp_init or mp_new.
78  * Frees all the memory allocated by this mempool and,
79  * if created by \ref mp_new(), the \p pool itself.
80  **/
81 void mp_delete(struct mempool *pool);
82 
83 /**
84  * Frees all data on a memory pool, but leaves it working.
85  * It can keep some of the chunks allocated to serve
86  * further allocation requests. Leaves the \p pool alive,
87  * even if it was created with \ref mp_new().
88  **/
89 void mp_flush(struct mempool *pool);
90 
91 /**
92  * Compute some statistics for debug purposes.
93  * See the definition of the <<struct_mempool_stats,mempool_stats structure>>.
94  **/
95 void mp_stats(struct mempool *pool, struct mempool_stats *stats);
96 uint64_t mp_total_size(struct mempool *pool);	/** How many bytes were allocated by the pool. **/
97 
98 /***
99  * [[alloc]]
100  * Allocation routines
101  * -------------------
102  ***/
103 
104 /**
105  * The function allocates new \p size bytes on a given memory pool.
106  * If the \p size is zero, the resulting pointer is undefined,
107  * but it may be safely reallocated or used as the parameter
108  * to other functions below.
109  *
110  * The resulting pointer is always aligned to a multiple of
111  * `CPU_STRUCT_ALIGN` bytes and this condition remains true also
112  * after future reallocations.
113  **/
114 void *mp_alloc(struct mempool *pool, unsigned size);
115 
116 /**
117  * The same as \ref mp_alloc(), but the result may be unaligned.
118  **/
119 void *mp_alloc_noalign(struct mempool *pool, unsigned size);
120 
121 /**
122  * The same as \ref mp_alloc(), but fills the newly allocated memory with zeroes.
123  **/
124 void *mp_alloc_zero(struct mempool *pool, unsigned size);
125