/src/php-src/Zend/zend_alloc.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Zend Engine | |
4 | | +----------------------------------------------------------------------+ |
5 | | | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | |
6 | | +----------------------------------------------------------------------+ |
7 | | | This source file is subject to version 2.00 of the Zend license, | |
8 | | | that is bundled with this package in the file LICENSE, and is | |
9 | | | available through the world-wide-web at the following url: | |
10 | | | http://www.zend.com/license/2_00.txt. | |
11 | | | If you did not receive a copy of the Zend license and are unable to | |
12 | | | obtain it through the world-wide-web, please send a note to | |
13 | | | license@zend.com so we can mail you a copy immediately. | |
14 | | +----------------------------------------------------------------------+ |
15 | | | Authors: Andi Gutmans <andi@php.net> | |
16 | | | Zeev Suraski <zeev@php.net> | |
17 | | | Dmitry Stogov <dmitry@php.net> | |
18 | | +----------------------------------------------------------------------+ |
19 | | */ |
20 | | |
21 | | #ifndef ZEND_ALLOC_H |
22 | | #define ZEND_ALLOC_H |
23 | | |
24 | | #include <stdio.h> |
25 | | |
26 | | #include "../TSRM/TSRM.h" |
27 | | #include "zend.h" |
28 | | |
29 | | #ifndef ZEND_MM_ALIGNMENT |
30 | | # define ZEND_MM_ALIGNMENT Z_UL(8) |
31 | | # define ZEND_MM_ALIGNMENT_LOG2 Z_L(3) |
32 | | #elif ZEND_MM_ALIGNMENT < 4 |
33 | | # undef ZEND_MM_ALIGNMENT |
34 | | # undef ZEND_MM_ALIGNMENT_LOG2 |
35 | | # define ZEND_MM_ALIGNMENT Z_UL(4) |
36 | | # define ZEND_MM_ALIGNMENT_LOG2 Z_L(2) |
37 | | #endif |
38 | | |
39 | 388M | #define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT - 1) |
40 | | |
41 | 388M | #define ZEND_MM_ALIGNED_SIZE(size) (((size) + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK) |
42 | | |
43 | | #define ZEND_MM_ALIGNED_SIZE_EX(size, alignment) \ |
44 | 817k | (((size) + ((alignment) - 1)) & ~((alignment) - 1)) |
45 | | |
46 | | typedef struct _zend_leak_info { |
47 | | void *addr; |
48 | | size_t size; |
49 | | const char *filename; |
50 | | const char *orig_filename; |
51 | | uint32_t lineno; |
52 | | uint32_t orig_lineno; |
53 | | } zend_leak_info; |
54 | | |
55 | | #if ZEND_DEBUG |
56 | | typedef struct _zend_mm_debug_info { |
57 | | size_t size; |
58 | | const char *filename; |
59 | | const char *orig_filename; |
60 | | uint32_t lineno; |
61 | | uint32_t orig_lineno; |
62 | | } zend_mm_debug_info; |
63 | | |
64 | 227M | # define ZEND_MM_OVERHEAD ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)) |
65 | | #else |
66 | | # define ZEND_MM_OVERHEAD 0 |
67 | | #endif |
68 | | |
69 | | BEGIN_EXTERN_C() |
70 | | |
71 | | ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) ZEND_ATTRIBUTE_MALLOC; |
72 | | |
73 | | 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); |
74 | | 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; |
75 | | ZEND_API void* ZEND_FASTCALL _safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC; |
76 | | ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); |
77 | | 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); |
78 | | 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); |
79 | | 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); |
80 | | 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); |
81 | | ZEND_API void* ZEND_FASTCALL _safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset); |
82 | | ZEND_API char* ZEND_FASTCALL _estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; |
83 | | ZEND_API char* ZEND_FASTCALL _estrndup(const char *s, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; |
84 | | ZEND_API size_t ZEND_FASTCALL _zend_mem_block_size(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); |
85 | | |
86 | | #include "zend_alloc_sizes.h" |
87 | | |
88 | | /* _emalloc() & _efree() specialization */ |
89 | | #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P) |
90 | | |
91 | | # define _ZEND_BIN_ALLOCATOR_DEF(_num, _size, _elements, _pages, x, y) \ |
92 | | ZEND_API void* ZEND_FASTCALL _emalloc_ ## _size(void) ZEND_ATTRIBUTE_MALLOC; |
93 | | |
94 | | ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_DEF, x, y) |
95 | | |
96 | | ZEND_API void* ZEND_FASTCALL _emalloc_large(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); |
97 | | ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); |
98 | | |
99 | | # define _ZEND_BIN_ALLOCATOR_SELECTOR_START(_num, _size, _elements, _pages, size, y) \ |
100 | | ((size <= _size) ? _emalloc_ ## _size() : |
101 | | # define _ZEND_BIN_ALLOCATOR_SELECTOR_END(_num, _size, _elements, _pages, size, y) \ |
102 | | ) |
103 | | |
104 | | # define ZEND_ALLOCATOR(size) \ |
105 | | ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_SELECTOR_START, size, y) \ |
106 | | ((size <= ZEND_MM_MAX_LARGE_SIZE) ? _emalloc_large(size) : _emalloc_huge(size)) \ |
107 | | ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR_SELECTOR_END, size, y) |
108 | | |
109 | | # define _emalloc(size) \ |
110 | | (__builtin_constant_p(size) ? \ |
111 | | ZEND_ALLOCATOR(size) \ |
112 | | : \ |
113 | | _emalloc(size) \ |
114 | | ) |
115 | | |
116 | | # define _ZEND_BIN_DEALLOCATOR_DEF(_num, _size, _elements, _pages, x, y) \ |
117 | | ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *); |
118 | | |
119 | | ZEND_MM_BINS_INFO(_ZEND_BIN_DEALLOCATOR_DEF, x, y) |
120 | | |
121 | | ZEND_API void ZEND_FASTCALL _efree_large(void *, size_t size); |
122 | | ZEND_API void ZEND_FASTCALL _efree_huge(void *, size_t size); |
123 | | |
124 | | # define _ZEND_BIN_DEALLOCATOR_SELECTOR_START(_num, _size, _elements, _pages, ptr, size) \ |
125 | | if (size <= _size) { _efree_ ## _size(ptr); } else |
126 | | |
127 | | # define ZEND_DEALLOCATOR(ptr, size) \ |
128 | | ZEND_MM_BINS_INFO(_ZEND_BIN_DEALLOCATOR_SELECTOR_START, ptr, size) \ |
129 | | if (size <= ZEND_MM_MAX_LARGE_SIZE) { _efree_large(ptr, size); } \ |
130 | | else { _efree_huge(ptr, size); } |
131 | | |
132 | | # define efree_size(ptr, size) do { \ |
133 | | if (__builtin_constant_p(size)) { \ |
134 | | ZEND_DEALLOCATOR(ptr, size) \ |
135 | | } else { \ |
136 | | _efree(ptr); \ |
137 | | } \ |
138 | | } while (0) |
139 | | # define efree_size_rel(ptr, size) \ |
140 | | efree_size(ptr, size) |
141 | | |
142 | | #else |
143 | | |
144 | | # define efree_size(ptr, size) \ |
145 | 5.52M | efree(ptr) |
146 | | # define efree_size_rel(ptr, size) \ |
147 | | efree_rel(ptr) |
148 | | |
149 | 20.1k | #define _emalloc_large _emalloc |
150 | | #define _emalloc_huge _emalloc |
151 | | #define _efree_large _efree |
152 | | #define _efree_huge _efree |
153 | | |
154 | | #endif |
155 | | |
156 | | /* Standard wrapper macros */ |
157 | 435M | #define emalloc(size) _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
158 | 20.1k | #define emalloc_large(size) _emalloc_large((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
159 | | #define emalloc_huge(size) _emalloc_huge((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
160 | 637k | #define safe_emalloc(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
161 | 477M | #define efree(ptr) _efree((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
162 | | #define efree_large(ptr) _efree_large((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
163 | | #define efree_huge(ptr) _efree_huge((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
164 | 55.7k | #define ecalloc(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
165 | 4.09M | #define erealloc(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
166 | 21.8k | #define erealloc2(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
167 | 6.29M | #define safe_erealloc(ptr, nmemb, size, offset) _safe_erealloc((ptr), (nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
168 | | #define erealloc_recoverable(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
169 | | #define erealloc2_recoverable(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
170 | 182k | #define estrdup(s) _estrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
171 | 34.6M | #define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
172 | | #define zend_mem_block_size(ptr) _zend_mem_block_size((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
173 | | |
174 | | /* Relay wrapper macros */ |
175 | | #define emalloc_rel(size) _emalloc((size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
176 | | #define safe_emalloc_rel(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
177 | | #define efree_rel(ptr) _efree((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
178 | | #define ecalloc_rel(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
179 | | #define erealloc_rel(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
180 | | #define erealloc2_rel(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
181 | | #define erealloc_recoverable_rel(ptr, size) _erealloc((ptr), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
182 | | #define erealloc2_recoverable_rel(ptr, size, copy_size) _erealloc2((ptr), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
183 | | #define safe_erealloc_rel(ptr, nmemb, size, offset) _safe_erealloc((ptr), (nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
184 | | #define estrdup_rel(s) _estrdup((s) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
185 | | #define estrndup_rel(s, length) _estrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
186 | | #define zend_mem_block_size_rel(ptr) _zend_mem_block_size((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
187 | | |
188 | | ZEND_API void * __zend_malloc(size_t len) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); |
189 | | ZEND_API void * __zend_calloc(size_t nmemb, size_t len) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2); |
190 | | ZEND_API void * __zend_realloc(void *p, size_t len) ZEND_ATTRIBUTE_ALLOC_SIZE(2); |
191 | | |
192 | | /* Selective persistent/non persistent allocation macros */ |
193 | 295M | #define pemalloc(size, persistent) ((persistent)?__zend_malloc(size):emalloc(size)) |
194 | 7.50k | #define safe_pemalloc(nmemb, size, offset, persistent) ((persistent)?_safe_malloc(nmemb, size, offset):safe_emalloc(nmemb, size, offset)) |
195 | 46.3M | #define pefree(ptr, persistent) ((persistent)?free(ptr):efree(ptr)) |
196 | | #define pefree_size(ptr, size, persistent) do { \ |
197 | | if (persistent) { \ |
198 | | free(ptr); \ |
199 | | } else { \ |
200 | | efree_size(ptr, size);\ |
201 | | } \ |
202 | | } while (0) |
203 | | |
204 | 24.5k | #define pecalloc(nmemb, size, persistent) ((persistent)?__zend_calloc((nmemb), (size)):ecalloc((nmemb), (size))) |
205 | 1.92M | #define perealloc(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc((ptr), (size))) |
206 | | #define perealloc2(ptr, size, copy_size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc2((ptr), (size), (copy_size))) |
207 | 0 | #define safe_perealloc(ptr, nmemb, size, offset, persistent) ((persistent)?_safe_realloc((ptr), (nmemb), (size), (offset)):safe_erealloc((ptr), (nmemb), (size), (offset))) |
208 | | #define perealloc_recoverable(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable((ptr), (size))) |
209 | | #define perealloc2_recoverable(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc2_recoverable((ptr), (size), (copy_size))) |
210 | 54 | #define pestrdup(s, persistent) ((persistent)?strdup(s):estrdup(s)) |
211 | | #define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length))) |
212 | | |
213 | | #define pemalloc_rel(size, persistent) ((persistent)?__zend_malloc(size):emalloc_rel(size)) |
214 | | #define pefree_rel(ptr, persistent) ((persistent)?free(ptr):efree_rel(ptr)) |
215 | | #define pecalloc_rel(nmemb, size, persistent) ((persistent)?__zend_calloc((nmemb), (size)):ecalloc_rel((nmemb), (size))) |
216 | | #define perealloc_rel(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc_rel((ptr), (size))) |
217 | | #define perealloc2_rel(ptr, size, copy_size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc2_rel((ptr), (size), (copy_size))) |
218 | | #define perealloc_recoverable_rel(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable_rel((ptr), (size))) |
219 | | #define perealloc2_recoverable_rel(ptr, size, copy_size, persistent) ((persistent)?realloc((ptr), (size)):erealloc2_recoverable_rel((ptr), (size), (copy_size))) |
220 | | #define pestrdup_rel(s, persistent) ((persistent)?strdup(s):estrdup_rel(s)) |
221 | | |
222 | | ZEND_API void zend_set_memory_limit(size_t memory_limit); |
223 | | |
224 | | ZEND_API void start_memory_manager(void); |
225 | | ZEND_API void shutdown_memory_manager(bool silent, bool full_shutdown); |
226 | | ZEND_API bool is_zend_mm(void); |
227 | | ZEND_API bool is_zend_ptr(const void *ptr); |
228 | | |
229 | | ZEND_API size_t zend_memory_usage(bool real_usage); |
230 | | ZEND_API size_t zend_memory_peak_usage(bool real_usage); |
231 | | |
232 | | /* fast cache for HashTables */ |
233 | | #define ALLOC_HASHTABLE(ht) \ |
234 | 126k | (ht) = (HashTable *) emalloc(sizeof(HashTable)) |
235 | | |
236 | | #define FREE_HASHTABLE(ht) \ |
237 | 5.06M | efree_size(ht, sizeof(HashTable)) |
238 | | |
239 | | #define ALLOC_HASHTABLE_REL(ht) \ |
240 | | (ht) = (HashTable *) emalloc_rel(sizeof(HashTable)) |
241 | | |
242 | | #define FREE_HASHTABLE_REL(ht) \ |
243 | | efree_size_rel(ht, sizeof(HashTable)) |
244 | | |
245 | | /* Heap functions */ |
246 | | typedef struct _zend_mm_heap zend_mm_heap; |
247 | | |
248 | | ZEND_API zend_mm_heap *zend_mm_startup(void); |
249 | | ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full_shutdown, bool silent); |
250 | | 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; |
251 | | ZEND_API void ZEND_FASTCALL _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); |
252 | | 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); |
253 | | 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); |
254 | | 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); |
255 | | |
256 | | #define zend_mm_alloc(heap, size) _zend_mm_alloc((heap), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
257 | | #define zend_mm_free(heap, p) _zend_mm_free((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
258 | | #define zend_mm_realloc(heap, p, size) _zend_mm_realloc((heap), (p), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
259 | | #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) |
260 | | #define zend_mm_block_size(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
261 | | |
262 | | #define zend_mm_alloc_rel(heap, size) _zend_mm_alloc((heap), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
263 | | #define zend_mm_free_rel(heap, p) _zend_mm_free((heap), (p) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
264 | | #define zend_mm_realloc_rel(heap, p, size) _zend_mm_realloc((heap), (p), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) |
265 | | #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) |
266 | | #define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) |
267 | | |
268 | | ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap); |
269 | | ZEND_API zend_mm_heap *zend_mm_get_heap(void); |
270 | | |
271 | | ZEND_API size_t zend_mm_gc(zend_mm_heap *heap); |
272 | | |
273 | 0 | #define ZEND_MM_CUSTOM_HEAP_NONE 0 |
274 | 3.50k | #define ZEND_MM_CUSTOM_HEAP_STD 1 |
275 | 957M | #define ZEND_MM_CUSTOM_HEAP_DEBUG 2 |
276 | | |
277 | | ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap); |
278 | | ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, |
279 | | void* (*_malloc)(size_t), |
280 | | void (*_free)(void*), |
281 | | void* (*_realloc)(void*, size_t)); |
282 | | ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, |
283 | | void* (**_malloc)(size_t), |
284 | | void (**_free)(void*), |
285 | | void* (**_realloc)(void*, size_t)); |
286 | | |
287 | | #if ZEND_DEBUG |
288 | | ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap, |
289 | | void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), |
290 | | void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), |
291 | | void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)); |
292 | | #endif |
293 | | |
294 | | typedef struct _zend_mm_storage zend_mm_storage; |
295 | | |
296 | | typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment); |
297 | | typedef void (*zend_mm_chunk_free_t)(zend_mm_storage *storage, void *chunk, size_t size); |
298 | | typedef bool (*zend_mm_chunk_truncate_t)(zend_mm_storage *storage, void *chunk, size_t old_size, size_t new_size); |
299 | | typedef bool (*zend_mm_chunk_extend_t)(zend_mm_storage *storage, void *chunk, size_t old_size, size_t new_size); |
300 | | |
301 | | typedef struct _zend_mm_handlers { |
302 | | zend_mm_chunk_alloc_t chunk_alloc; |
303 | | zend_mm_chunk_free_t chunk_free; |
304 | | zend_mm_chunk_truncate_t chunk_truncate; |
305 | | zend_mm_chunk_extend_t chunk_extend; |
306 | | } zend_mm_handlers; |
307 | | |
308 | | struct _zend_mm_storage { |
309 | | const zend_mm_handlers handlers; |
310 | | void *data; |
311 | | }; |
312 | | |
313 | | ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap); |
314 | | ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void *data, size_t data_size); |
315 | | |
316 | | /* |
317 | | |
318 | | // The following example shows how to use zend_mm_heap API with custom storage |
319 | | |
320 | | static zend_mm_heap *apc_heap = NULL; |
321 | | static HashTable *apc_ht = NULL; |
322 | | |
323 | | typedef struct _apc_data { |
324 | | void *mem; |
325 | | uint32_t free_pages; |
326 | | } apc_data; |
327 | | |
328 | | static void *apc_chunk_alloc(zend_mm_storage *storage, size_t size, size_t alignment) |
329 | | { |
330 | | apc_data *data = (apc_data*)(storage->data); |
331 | | size_t real_size = ((size + (ZEND_MM_CHUNK_SIZE-1)) & ~(ZEND_MM_CHUNK_SIZE-1)); |
332 | | uint32_t count = real_size / ZEND_MM_CHUNK_SIZE; |
333 | | uint32_t first, last, i; |
334 | | |
335 | | ZEND_ASSERT(alignment == ZEND_MM_CHUNK_SIZE); |
336 | | |
337 | | for (first = 0; first < 32; first++) { |
338 | | if (!(data->free_pages & (1 << first))) { |
339 | | last = first; |
340 | | do { |
341 | | if (last - first == count - 1) { |
342 | | for (i = first; i <= last; i++) { |
343 | | data->free_pages |= (1 << i); |
344 | | } |
345 | | return (void *)(((char*)(data->mem)) + ZEND_MM_CHUNK_SIZE * (1 << first)); |
346 | | } |
347 | | last++; |
348 | | } while (last < 32 && !(data->free_pages & (1 << last))); |
349 | | first = last; |
350 | | } |
351 | | } |
352 | | return NULL; |
353 | | } |
354 | | |
355 | | static void apc_chunk_free(zend_mm_storage *storage, void *chunk, size_t size) |
356 | | { |
357 | | apc_data *data = (apc_data*)(storage->data); |
358 | | uint32_t i; |
359 | | |
360 | | ZEND_ASSERT(((uintptr_t)chunk & (ZEND_MM_CHUNK_SIZE - 1)) == 0); |
361 | | |
362 | | i = ((uintptr_t)chunk - (uintptr_t)(data->mem)) / ZEND_MM_CHUNK_SIZE; |
363 | | while (1) { |
364 | | data->free_pages &= ~(1 << i); |
365 | | if (size <= ZEND_MM_CHUNK_SIZE) { |
366 | | break; |
367 | | } |
368 | | size -= ZEND_MM_CHUNK_SIZE; |
369 | | } |
370 | | } |
371 | | |
372 | | static void apc_init_heap(void) |
373 | | { |
374 | | zend_mm_handlers apc_handlers = { |
375 | | apc_chunk_alloc, |
376 | | apc_chunk_free, |
377 | | NULL, |
378 | | NULL, |
379 | | }; |
380 | | apc_data tmp_data; |
381 | | zend_mm_heap *old_heap; |
382 | | |
383 | | // Preallocate properly aligned SHM chunks (64MB) |
384 | | tmp_data.mem = shm_memalign(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE * 32); |
385 | | |
386 | | // Initialize temporary storage data |
387 | | tmp_data.free_pages = 0; |
388 | | |
389 | | // Create heap |
390 | | apc_heap = zend_mm_startup_ex(&apc_handlers, &tmp_data, sizeof(tmp_data)); |
391 | | |
392 | | // Allocate some data in the heap |
393 | | old_heap = zend_mm_set_heap(apc_heap); |
394 | | ALLOC_HASHTABLE(apc_ht); |
395 | | zend_hash_init(apc_ht, 64, NULL, ZVAL_PTR_DTOR, 0); |
396 | | zend_mm_set_heap(old_heap); |
397 | | } |
398 | | |
399 | | */ |
400 | | |
401 | | #ifdef ZTS |
402 | | size_t zend_mm_globals_size(void); |
403 | | #endif |
404 | | |
405 | | END_EXTERN_C() |
406 | | |
407 | | #endif |