1 #ifndef EL__UTIL_MEMORY_H
2 #define EL__UTIL_MEMORY_H
3 
4 /* If defined, we'll crash if ALLOC_MAXTRIES is attained,
5  * if not defined, we'll try to continue. */
6 /* #define CRASH_IF_ALLOC_MAXTRIES */
7 
8 /* Max. number of retry in case of memory allocation failure. */
9 #define ALLOC_MAXTRIES 3
10 
11 /* Delay in seconds between each alloc try. */
12 #define ALLOC_DELAY 3
13 
14 #define fmem_alloc(x) mem_alloc(x)
15 #define fmem_free(x) mem_free(x)
16 
17 
18 /* Cygwin wants some size_t definition here... let's try to make it happy
19  * then. Hrmpf. */
20 #include <sys/types.h>
21 #include <stddef.h>
22 
23 #ifdef HAVE_MMAP
24 void *mem_mmap_alloc(size_t size);
25 void mem_mmap_free(void *p, size_t size);
26 void *mem_mmap_realloc(void *p, size_t old_size, size_t new_size);
27 #else
28 #define mem_mmap_alloc(x) mem_alloc(x)
29 #define mem_mmap_free(x, y) mem_free(x)
30 #define mem_mmap_realloc(x, y, z) mem_realloc(x, z)
31 #endif
32 
33 
34 #ifdef DEBUG_MEMLEAK
35 
36 #include "util/memdebug.h"
37 
38 #define mem_alloc(x) debug_mem_alloc(__FILE__, __LINE__, x)
39 #define mem_calloc(x, y) debug_mem_calloc(__FILE__, __LINE__, x, y)
40 #define mem_free(x) debug_mem_free(__FILE__, __LINE__, x)
41 #define mem_realloc(x, y) debug_mem_realloc(__FILE__, __LINE__, x, y)
42 
43 #else
44 
45 #ifndef CONFIG_FASTMEM
46 
47 void *mem_alloc(size_t);
48 void *mem_calloc(size_t, size_t);
49 void mem_free(void *);
50 void *mem_realloc(void *, size_t);
51 
52 #else
53 
54 # include <stdlib.h>
55 
56 /* TODO: For enhanced portability, checks at configure time:
57  * malloc(0) -> NULL
58  * realloc(NULL, 0) -> NULL
59  * realloc(p, 0) <-> free(p)
60  * realloc(NULL, n) <-> malloc(n)
61  * Some old implementations may not respect these rules.
62  * For these we need some replacement functions.
63  * This should not be an issue on most modern systems.
64  */
65 
66 # define mem_alloc(size) malloc(size)
67 # define mem_calloc(count, size) calloc(count, size)
68 # define mem_free(p) free(p)
69 # define mem_realloc(p, size) realloc(p, size)
70 
71 
72 /* fmem_* functions should be use for allocation and freeing of memory
73  * inside a function.
74  * See alloca(3) manpage. */
75 
76 #undef fmem_alloc
77 #undef fmem_free
78 
79 #ifdef HAVE_ALLOCA
80 
81 #ifdef HAVE_ALLOCA_H
82 #include <alloca.h>
83 #endif
84 #define fmem_alloc(x) alloca(x)
85 #define fmem_free(x)
86 
87 #else /* HAVE_ALLOCA */
88 
89 #define fmem_alloc(x) mem_alloc(x)
90 #define fmem_free(x) mem_free(x)
91 
92 #endif /* HAVE_ALLOCA */
93 
94 #endif /* CONFIG_FASTMEM */
95 
96 #endif /* DEBUG_MEMLEAK */
97 
98 
99 /* Granular memory allocation. */
100 
101 /* The ``old'' style granularity. XXX: Must be power of 2 */
102 #define ALLOC_GR 0x100
103 
104 #include <string.h> /* for memset() */
105 
106 /* The granularity used by the aligned memory functions below must be a mask
107  * with all bits set from but not including the most significant bit and down.
108  * So if an alignment of 256 is wanted use 0xFF. */
109 
110 #define ALIGN_MEMORY_SIZE(x, gr) (((x) + (gr)) & ~(gr))
111 
112 static inline void *
mem_align_alloc__(unsigned char * file,int line,void ** ptr,size_t old,size_t new,size_t objsize,size_t mask)113 mem_align_alloc__(
114 #ifdef DEBUG_MEMLEAK
115 		  unsigned char *file, int line,
116 #endif
117 		  void **ptr, size_t old, size_t new, size_t objsize, size_t mask)
118 {
119 	size_t newsize = ALIGN_MEMORY_SIZE(new, mask);
120 	size_t oldsize = ALIGN_MEMORY_SIZE(old, mask);
121 
122 	if (newsize > oldsize) {
123 		unsigned char *data;
124 
125 		newsize *= objsize;
126 		oldsize *= objsize;
127 
128 #ifdef DEBUG_MEMLEAK
129 		data = debug_mem_realloc(file, line, *ptr, newsize);
130 #else
131 		data = mem_realloc(*ptr, newsize);
132 #endif
133 		if (!data) return NULL;
134 
135 		*ptr = (void *) data;
136 		memset(&data[oldsize], 0, newsize - oldsize);
137 	}
138 
139 	return *ptr;
140 }
141 
142 #ifdef DEBUG_MEMLEAK
143 #define mem_align_alloc(ptr, old, new, obj, mask) \
144 	mem_align_alloc__(__FILE__, __LINE__, (void **) ptr, old, new, sizeof(obj), mask)
145 #else
146 #define mem_align_alloc(ptr, old, new, obj, mask) \
147 	mem_align_alloc__((void **) ptr, old, new, sizeof(obj), mask)
148 #endif
149 
150 
151 /* Maybe-free macros */
152 /* TODO: Think about making what they do more obvious in their identifier, they
153  * could be obfuscating their users a little for the newcomers otherwise. */
154 
155 #define mem_free_set(x, v) do { if (*(x)) mem_free(*(x)); *(x) = (v); } while (0)
156 #define mem_free_if(x) do { register void *p = (x); if (p) mem_free(p); } while (0)
157 
158 #if 0
159 /* This may help to find bugs. */
160 #undef mem_free_if
161 #define mem_free_if(x) mem_free_set(&x, NULL)
162 #endif
163 
164 
165 /* This is out of place, but there is no better place. */
166 
167 #ifdef DEBUG_MEMLEAK
168 #define intdup(i) intdup__(__FILE__, __LINE__, i)
169 #else
170 #define intdup(i) intdup__(i)
171 #endif
172 
173 static inline int *
intdup__(unsigned char * file,int line,int i)174 intdup__(
175 #ifdef DEBUG_MEMLEAK
176          unsigned char *file, int line,
177 #endif
178          int i)
179 {
180 #ifdef DEBUG_MEMLEAK
181 	int *p = debug_mem_alloc(file, line, sizeof(*p));
182 #else
183 	int *p = mem_alloc(sizeof(*p));
184 #endif
185 
186 	if (p) *p = i;
187 
188 	return p;
189 }
190 
191 #endif
192