1 /** Memory allocation manager
5 #define _GNU_SOURCE /* MREMAP_MAYMOVE */
13 #include <sys/types.h>
21 #include "util/error.h"
22 #include "util/memory.h"
25 #if !defined(DEBUG_MEMLEAK) && !defined(CONFIG_FASTMEM)
27 static int alloc_try
= 0;
30 patience(unsigned char *of
)
33 if (alloc_try
< ALLOC_MAXTRIES
) {
34 ERROR("Out of memory (%s returned NULL): retry #%d/%d, "
35 "I still exercise my patience and retry tirelessly.",
36 of
, alloc_try
, ALLOC_MAXTRIES
);
41 #ifdef CRASH_IF_ALLOC_MAXTRIES
42 INTERNAL("Out of memory (%s returned NULL) after %d tries, "
43 "I give up. See ya on the other side.",
46 ERROR("Out of memory (%s returned NULL) after %d tries, "
47 "I give up and try to continue. Pray for me, please.",
55 mem_alloc(size_t size
)
59 void *p
= malloc(size
);
61 } while (patience("malloc"));
67 mem_calloc(size_t count
, size_t eltsize
)
71 void *p
= calloc(count
, eltsize
);
73 } while (patience("calloc"));
82 INTERNAL("mem_free(NULL)");
89 mem_realloc(void *p
, size_t size
)
91 if (!p
) return mem_alloc(size
);
95 void *p2
= realloc(p
, size
);
97 } while (patience("realloc"));
107 /* TODO: Leak detector and the usual protection gear? patience()?
109 * We could just alias mem_mmap_* to mem_debug_* #if DEBUG_MEMLEAK, *WHEN* we are
110 * confident that the mmap() code is really bugless ;-). --pasky */
114 static int page_size
;
116 /** Round up to a full page.
117 * This tries to prevent useless reallocations, especially since they
118 * are quite expensive in the mremap()-less case. */
120 round_size(size_t size
)
122 #ifdef HAVE_SC_PAGE_SIZE
123 if (!page_size
) page_size
= sysconf(_SC_PAGE_SIZE
);
125 if (page_size
<= 0) page_size
= 1;
126 return (size
/ page_size
+ 1) * page_size
;
129 /** Some systems may not have MAP_ANON but MAP_ANONYMOUS instead. */
130 #if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
131 #define MAP_ANON MAP_ANONYMOUS
135 mem_mmap_alloc(size_t size
)
138 void *p
= mmap(NULL
, round_size(size
), PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
, -1, 0);
148 mem_mmap_free(void *p
, size_t size
)
151 INTERNAL("mem_mmap_free(NULL)");
155 munmap(p
, round_size(size
));
159 mem_mmap_realloc(void *p
, size_t old_size
, size_t new_size
)
161 if (!p
) return mem_mmap_alloc(new_size
);
163 if (round_size(old_size
) == round_size(new_size
))
168 void *p2
= mremap(p
, round_size(old_size
), round_size(new_size
), MREMAP_MAYMOVE
);
170 if (p2
!= MAP_FAILED
)
173 void *p2
= mem_mmap_alloc(new_size
);
176 memcpy(p2
, p
, MIN(old_size
, new_size
));
177 mem_mmap_free(p
, old_size
);
182 mem_mmap_free(p
, old_size
);