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
)
60 void *p
= GC_MALLOC(size
);
62 void *p
= malloc(size
);
65 } while (patience("malloc"));
71 mem_calloc(size_t count
, size_t eltsize
)
76 void *p
= GC_MALLOC(count
* eltsize
);
78 void *p
= calloc(count
, eltsize
);
81 } while (patience("calloc"));
90 INTERNAL("mem_free(NULL)");
101 mem_realloc(void *p
, size_t size
)
103 if (!p
) return mem_alloc(size
);
108 void *p2
= GC_REALLOC(p
, size
);
110 void *p2
= realloc(p
, size
);
113 } while (patience("realloc"));
123 /* TODO: Leak detector and the usual protection gear? patience()?
125 * We could just alias mem_mmap_* to mem_debug_* #if DEBUG_MEMLEAK, *WHEN* we are
126 * confident that the mmap() code is really bugless ;-). --pasky */
130 static int page_size
;
132 /** Round up to a full page.
133 * This tries to prevent useless reallocations, especially since they
134 * are quite expensive in the mremap()-less case. */
136 round_size(size_t size
)
138 #ifdef HAVE_SC_PAGE_SIZE
139 if (!page_size
) page_size
= sysconf(_SC_PAGE_SIZE
);
141 if (page_size
<= 0) page_size
= 1;
142 return (size
/ page_size
+ 1) * page_size
;
145 /** Some systems may not have MAP_ANON but MAP_ANONYMOUS instead. */
146 #if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
147 #define MAP_ANON MAP_ANONYMOUS
151 mem_mmap_alloc(size_t size
)
154 void *p
= mmap(NULL
, round_size(size
), PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_ANON
, -1, 0);
164 mem_mmap_free(void *p
, size_t size
)
167 INTERNAL("mem_mmap_free(NULL)");
171 munmap(p
, round_size(size
));
175 mem_mmap_realloc(void *p
, size_t old_size
, size_t new_size
)
177 if (!p
) return mem_mmap_alloc(new_size
);
179 if (round_size(old_size
) == round_size(new_size
))
184 void *p2
= mremap(p
, round_size(old_size
), round_size(new_size
), MREMAP_MAYMOVE
);
186 if (p2
!= MAP_FAILED
)
189 void *p2
= mem_mmap_alloc(new_size
);
192 memcpy(p2
, p
, MIN(old_size
, new_size
));
193 mem_mmap_free(p
, old_size
);
198 mem_mmap_free(p
, old_size
);