1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #ifndef ZEND_ALLOC_H
24 #define ZEND_ALLOC_H
25
26 #include <stdio.h>
27
28 #include "../TSRM/TSRM.h"
29 #include "zend.h"
30
31 #ifndef ZEND_MM_ALIGNMENT
32 # define ZEND_MM_ALIGNMENT Z_L(8)
33 # define ZEND_MM_ALIGNMENT_LOG2 Z_L(3)
34 #elif ZEND_MM_ALIGNMENT < 4
35 # undef ZEND_MM_ALIGNMENT
36 # undef ZEND_MM_ALIGNMENT_LOG2
37 # define ZEND_MM_ALIGNMENT Z_L(4)
38 # define ZEND_MM_ALIGNMENT_LOG2 Z_L(2)
39 #endif
40
41 #define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT - Z_L(1))
42
43 #define ZEND_MM_ALIGNED_SIZE(size) (((size) + ZEND_MM_ALIGNMENT - Z_L(1)) & ZEND_MM_ALIGNMENT_MASK)
44
45 #define ZEND_MM_ALIGNED_SIZE_EX(size, alignment) \
46 (((size) + ((alignment) - Z_L(1))) & ~((alignment) - Z_L(1)))
47
48 typedef struct _zend_leak_info {
49 void *addr;
50 size_t size;
51 const char *filename;
52 const char *orig_filename;
53 uint lineno;
54 uint orig_lineno;
55 } zend_leak_info;
56
57 #if ZEND_DEBUG
58 typedef struct _zend_mm_debug_info {
59 size_t size;
60 const char *filename;
61 const char *orig_filename;
62 uint lineno;
63 uint orig_lineno;
64 } zend_mm_debug_info;
65
66 # define ZEND_MM_OVERHEAD ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info))
67 #else
68 # define ZEND_MM_OVERHEAD 0
69 #endif
70
71 BEGIN_EXTERN_C()
72
73 ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) ZEND_ATTRIBUTE_MALLOC;
74
75 ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
76 ZEND_API void* ZEND_FASTCALL _safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
77 ZEND_API void* ZEND_FASTCALL _safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC;
78 ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
79 ZEND_API void* ZEND_FASTCALL _ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2);
80 ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2);
81 ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2);
82 ZEND_API void* ZEND_FASTCALL _safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
83 ZEND_API void* ZEND_FASTCALL _safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset);
84 ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
85 ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
86 ZEND_API size_t ZEND_FASTCALL _zend_mem_block_size(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
87
88 #include "zend_alloc_sizes.h"
89
90
91 #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P)
92
93 # define _ZEND_BIN_ALLOCATOR_DEF(_num, _size, _elements, _pages, x, y) \
94 ZEND_API void* ZEND_FASTCALL _emalloc_ ## _size(void) ZEND_ATTRIBUTE_MALLOC;
95
96 ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_DEF, x, y)
97
98 ZEND_API void* ZEND_FASTCALL _emalloc_large(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
99 ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
100
101 # define _ZEND_BIN_ALLOCATOR_SELECTOR_START(_num, _size, _elements, _pages, size, y) \
102 ((size <= _size) ? _emalloc_ ## _size() :
103 # define _ZEND_BIN_ALLOCATOR_SELECTOR_END(_num, _size, _elements, _pages, size, y) \
104 )
105
106 # define ZEND_ALLOCATOR(size) \
107 ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_SELECTOR_START, size, y) \
108 ((size <= ZEND_MM_MAX_LARGE_SIZE) ? _emalloc_large(size) : _emalloc_huge(size)) \
109 ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_SELECTOR_END, size, y)
110
111 # define _emalloc(size) \
112 (__builtin_constant_p(size) ? \
113 ZEND_ALLOCATOR(size) \
114 : \
115 _emalloc(size) \
116 )
117
118 # define _ZEND_BIN_DEALLOCATOR_DEF(_num, _size, _elements, _pages, x, y) \
119 ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *);
120
121 ZEND_MM_BINS_INFO(_ZEND_BIN_DEALLOCATOR_DEF, x, y)
122
123 ZEND_API void ZEND_FASTCALL _efree_large(void *, size_t size);
124 ZEND_API void ZEND_FASTCALL _efree_huge(void *, size_t size);
125
126 # define _ZEND_BIN_DEALLOCATOR_SELECTOR_START(_num, _size, _elements, _pages, ptr, size) \
127 if (size <= _size) { _efree_ ## _size(ptr); } else
128
129 # define ZEND_DEALLOCATOR(ptr, size) \
130 ZEND_MM_BINS_INFO(_ZEND_BIN_DEALLOCATOR_SELECTOR_START, ptr, size) \
131 if (size <= ZEND_MM_MAX_LARGE_SIZE) { _efree_large(ptr, size); } \
132 else { _efree_huge(ptr, size); }
133
134 # define efree_size(ptr, size) do { \
135 if (__builtin_constant_p(size)) { \
136 ZEND_DEALLOCATOR(ptr, size) \
137 } else { \
138 _efree(ptr); \
139 } \
140 } while (0)
141 # define efree_size_rel(ptr, size) \
142 efree_size(ptr, size)
143
144 #else
145
146 # define efree_size(ptr, size) \
147 efree(ptr)
148 # define efree_size_rel(ptr, size) \
149 efree_rel(ptr)
150
151 #define _emalloc_large _emalloc
152 #define _emalloc_huge _emalloc
153 #define _efree_large _efree
154 #define _efree_huge _efree
155
156 #endif
157
158
159 #define emalloc(size) _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
160 #define emalloc_large(size) _emalloc_large((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
161 #define emalloc_huge(size) _emalloc_huge((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
162 #define safe_emalloc(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
163 #define efree(ptr) _efree((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
164 #define efree_large(ptr) _efree_large((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
165 #define efree_huge(ptr) _efree_huge((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
166 #define ecalloc(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
167 #define erealloc(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
168 #define erealloc2(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
169 #define safe_erealloc(ptr, nmemb, size, offset) _safe_erealloc((ptr), (nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
170 #define erealloc_recoverable(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
171 #define erealloc2_recoverable(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
172 #define estrdup(s) _estrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
173 #define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
174 #define zend_mem_block_size(ptr) _zend_mem_block_size((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
175
176
177 #define emalloc_rel(size) _emalloc((size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
178 #define safe_emalloc_rel(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
179 #define efree_rel(ptr) _efree((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
180 #define ecalloc_rel(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
181 #define erealloc_rel(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
182 #define erealloc2_rel(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
183 #define erealloc_recoverable_rel(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
184 #define erealloc2_recoverable_rel(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
185 #define safe_erealloc_rel(ptr, nmemb, size, offset) _safe_erealloc((ptr), (nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
186 #define estrdup_rel(s) _estrdup((s) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
187 #define estrndup_rel(s, length) _estrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
188 #define zend_mem_block_size_rel(ptr) _zend_mem_block_size((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
189
190 ZEND_API void * __zend_malloc(size_t len) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
191 ZEND_API void * __zend_calloc(size_t nmemb, size_t len) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2);
192 ZEND_API void * __zend_realloc(void *p, size_t len) ZEND_ATTRIBUTE_ALLOC_SIZE(2);
193
194
195 #define pemalloc(size, persistent) ((persistent)?__zend_malloc(size):emalloc(size))
196 #define safe_pemalloc(nmemb, size, offset, persistent) ((persistent)?_safe_malloc(nmemb, size, offset):safe_emalloc(nmemb, size, offset))
197 #define pefree(ptr, persistent) ((persistent)?free(ptr):efree(ptr))
198 #define pefree_size(ptr, size, persistent) ((persistent)?free(ptr):efree_size(ptr, size))
199 #define pecalloc(nmemb, size, persistent) ((persistent)?__zend_calloc((nmemb), (size)):ecalloc((nmemb), (size)))
200 #define perealloc(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc((ptr), (size)))
201 #define perealloc2(ptr, size, copy_size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc2((ptr), (size), (copy_size)))
202 #define safe_perealloc(ptr, nmemb, size, offset, persistent) ((persistent)?_safe_realloc((ptr), (nmemb), (size), (offset)):safe_erealloc((ptr), (nmemb), (size), (offset)))
203 #define perealloc_recoverable(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable((ptr), (size)))
204 #define perealloc2_recoverable(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc2_recoverable((ptr), (size), (copy_size)))
205 #define pestrdup(s, persistent) ((persistent)?strdup(s):estrdup(s))
206 #define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
207
208 #define pemalloc_rel(size, persistent) ((persistent)?__zend_malloc(size):emalloc_rel(size))
209 #define pefree_rel(ptr, persistent) ((persistent)?free(ptr):efree_rel(ptr))
210 #define pecalloc_rel(nmemb, size, persistent) ((persistent)?__zend_calloc((nmemb), (size)):ecalloc_rel((nmemb), (size)))
211 #define perealloc_rel(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc_rel((ptr), (size)))
212 #define perealloc2_rel(ptr, size, copy_size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc2_rel((ptr), (size), (copy_size)))
213 #define perealloc_recoverable_rel(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable_rel((ptr), (size)))
214 #define perealloc2_recoverable_rel(ptr, size, copy_size, persistent) ((persistent)?realloc((ptr), (size)):erealloc2_recoverable_rel((ptr), (size), (copy_size)))
215 #define pestrdup_rel(s, persistent) ((persistent)?strdup(s):estrdup_rel(s))
216
217 ZEND_API int zend_set_memory_limit(size_t memory_limit);
218
219 ZEND_API void start_memory_manager(void);
220 ZEND_API void shutdown_memory_manager(int silent, int full_shutdown);
221 ZEND_API int is_zend_mm(void);
222
223 ZEND_API size_t zend_memory_usage(int real_usage);
224 ZEND_API size_t zend_memory_peak_usage(int real_usage);
225
226
227 #define ALLOC_HASHTABLE(ht) \
228 (ht) = (HashTable *) emalloc(sizeof(HashTable))
229
230 #define FREE_HASHTABLE(ht) \
231 efree_size(ht, sizeof(HashTable))
232
233 #define ALLOC_HASHTABLE_REL(ht) \
234 (ht) = (HashTable *) emalloc_rel(sizeof(HashTable))
235
236 #define FREE_HASHTABLE_REL(ht) \
237 efree_size_rel(ht, sizeof(HashTable))
238
239
240 typedef struct _zend_mm_heap zend_mm_heap;
241
242 ZEND_API zend_mm_heap *zend_mm_startup(void);
243 ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent);
244 ZEND_API void* ZEND_FASTCALL _zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
245 ZEND_API void ZEND_FASTCALL _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
246 ZEND_API void* ZEND_FASTCALL _zend_mm_realloc(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
247 ZEND_API void* ZEND_FASTCALL _zend_mm_realloc2(zend_mm_heap *heap, void *p, size_t size, size_t copy_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
248 ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
249
250 #define zend_mm_alloc(heap, size) _zend_mm_alloc((heap), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
251 #define zend_mm_free(heap, p) _zend_mm_free((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
252 #define zend_mm_realloc(heap, p, size) _zend_mm_realloc((heap), (p), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
253 #define zend_mm_realloc2(heap, p, size, copy_size) _zend_mm_realloc2((heap), (p), (size), (copy_size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
254 #define zend_mm_block_size(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
255
256 #define zend_mm_alloc_rel(heap, size) _zend_mm_alloc((heap), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
257 #define zend_mm_free_rel(heap, p) _zend_mm_free((heap), (p) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
258 #define zend_mm_realloc_rel(heap, p, size) _zend_mm_realloc((heap), (p), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
259 #define zend_mm_realloc2_rel(heap, p, size, copy_size) _zend_mm_realloc2((heap), (p), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
260 #define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
261
262 ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap);
263 ZEND_API zend_mm_heap *zend_mm_get_heap(void);
264
265 ZEND_API size_t zend_mm_gc(zend_mm_heap *heap);
266
267 #define ZEND_MM_CUSTOM_HEAP_NONE 0
268 #define ZEND_MM_CUSTOM_HEAP_STD 1
269 #define ZEND_MM_CUSTOM_HEAP_DEBUG 2
270
271 ZEND_API int zend_mm_is_custom_heap(zend_mm_heap *new_heap);
272 ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
273 void* (*_malloc)(size_t),
274 void (*_free)(void*),
275 void* (*_realloc)(void*, size_t));
276 ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
277 void* (**_malloc)(size_t),
278 void (**_free)(void*),
279 void* (**_realloc)(void*, size_t));
280
281 #if ZEND_DEBUG
282 ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap,
283 void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
284 void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC),
285 void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC));
286 #endif
287
288 typedef struct _zend_mm_storage zend_mm_storage;
289
290 typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment);
291 typedef void (*zend_mm_chunk_free_t)(zend_mm_storage *storage, void *chunk, size_t size);
292 typedef int (*zend_mm_chunk_truncate_t)(zend_mm_storage *storage, void *chunk, size_t old_size, size_t new_size);
293 typedef int (*zend_mm_chunk_extend_t)(zend_mm_storage *storage, void *chunk, size_t old_size, size_t new_size);
294
295 typedef struct _zend_mm_handlers {
296 zend_mm_chunk_alloc_t chunk_alloc;
297 zend_mm_chunk_free_t chunk_free;
298 zend_mm_chunk_truncate_t chunk_truncate;
299 zend_mm_chunk_extend_t chunk_extend;
300 } zend_mm_handlers;
301
302 struct _zend_mm_storage {
303 const zend_mm_handlers handlers;
304 void *data;
305 };
306
307 ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap);
308 ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void *data, size_t data_size);
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395 END_EXTERN_C()
396
397 #endif
398
399
400
401
402
403
404
405