1
2 #include "libimagequant.h"
3 #include "mempool.h"
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <assert.h>
7
8 #define ALIGN_MASK 15UL
9 #define MEMPOOL_RESERVED ((sizeof(struct mempool)+ALIGN_MASK) & ~ALIGN_MASK)
10
11 struct mempool
12 {
13 unsigned int used, size;
14 void *(*malloc) (size_t);
15 void (*free) (void *);
16 struct mempool *next;
17 };
18 LIQ_PRIVATE void *
mempool_create(mempool * mptr,const unsigned int size,unsigned int max_size,void * (* malloc)(size_t),void (* free)(void *))19 mempool_create (mempool * mptr, const unsigned int size, unsigned int max_size,
20 void *(*malloc) (size_t), void (*free) (void *))
21 {
22 mempool old;
23 uintptr_t mptr_used_start;
24
25 if (*mptr && ((*mptr)->used + size) <= (*mptr)->size) {
26 unsigned int prevused = (*mptr)->used;
27 (*mptr)->used += (size + 15UL) & ~0xFUL;
28 return ((char *) (*mptr)) + prevused;
29 }
30
31 old = *mptr;
32 if (!max_size)
33 max_size = (1 << 17);
34 max_size = size + ALIGN_MASK > max_size ? size + ALIGN_MASK : max_size;
35
36 *mptr = malloc (MEMPOOL_RESERVED + max_size);
37 if (!*mptr)
38 return NULL;
39 **mptr = (struct mempool) {
40 .malloc = malloc,.free = free,.size = MEMPOOL_RESERVED + max_size,.used =
41 sizeof (struct mempool),.next = old,};
42 mptr_used_start = (uintptr_t) (*mptr) + (*mptr)->used;
43 (*mptr)->used += (ALIGN_MASK + 1 - (mptr_used_start & ALIGN_MASK)) & ALIGN_MASK; // reserve bytes required to make subsequent allocations aligned
44 assert (!(((uintptr_t) (*mptr) + (*mptr)->used) & ALIGN_MASK));
45
46 return mempool_alloc (mptr, size, size);
47 }
48
49 LIQ_PRIVATE void *
mempool_alloc(mempool * mptr,unsigned int size,unsigned int max_size)50 mempool_alloc (mempool * mptr, unsigned int size, unsigned int max_size)
51 {
52 if (((*mptr)->used + size) <= (*mptr)->size) {
53 unsigned int prevused = (*mptr)->used;
54 (*mptr)->used += (size + ALIGN_MASK) & ~ALIGN_MASK;
55 return ((char *) (*mptr)) + prevused;
56 }
57
58 return mempool_create (mptr, size, max_size, (*mptr)->malloc, (*mptr)->free);
59 }
60
61 LIQ_PRIVATE void
mempool_destroy(mempool m)62 mempool_destroy (mempool m)
63 {
64 while (m) {
65 mempool next = m->next;
66 m->free (m);
67 m = next;
68 }
69 }
70