1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2014 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@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
21
22#ifndef ZEND_ALLOC_H
23#define ZEND_ALLOC_H
24
25#include <stdio.h>
26
27#include "../TSRM/TSRM.h"
28#include "zend.h"
29
30#ifndef ZEND_MM_ALIGNMENT
31# define ZEND_MM_ALIGNMENT 8
32# define ZEND_MM_ALIGNMENT_LOG2 3
33#elif ZEND_MM_ALIGNMENT < 4
34# undef ZEND_MM_ALIGNMENT
35# undef ZEND_MM_ALIGNMENT_LOG2
36# define ZEND_MM_ALIGNMENT 4
37# define ZEND_MM_ALIGNMENT_LOG2 2
38#endif
39
40#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1)
41
42#define ZEND_MM_ALIGNED_SIZE(size)  (((size) + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK)
43
44typedef struct _zend_leak_info {
45    void *addr;
46    size_t size;
47    const char *filename;
48    uint lineno;
49    const char *orig_filename;
50    uint orig_lineno;
51} zend_leak_info;
52
53BEGIN_EXTERN_C()
54
55ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_MALLOC;
56
57ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1);
58ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
59ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC;
60ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
61ZEND_API void *_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);
62ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2);
63ZEND_API void *_safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
64ZEND_API void *_safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset);
65ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
66ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
67ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
68
69/* Standard wrapper macros */
70#define emalloc(size)                       _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
71#define safe_emalloc(nmemb, size, offset)   _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
72#define efree(ptr)                          _efree((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
73#define ecalloc(nmemb, size)                _ecalloc((nmemb), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
74#define erealloc(ptr, size)                 _erealloc((ptr), (size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
75#define safe_erealloc(ptr, nmemb, size, offset) _safe_erealloc((ptr), (nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
76#define erealloc_recoverable(ptr, size)     _erealloc((ptr), (size), 1 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
77#define estrdup(s)                          _estrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
78#define estrndup(s, length)                 _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
79#define zend_mem_block_size(ptr)            _zend_mem_block_size((ptr) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
80
81/* Relay wrapper macros */
82#define emalloc_rel(size)                       _emalloc((size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
83#define safe_emalloc_rel(nmemb, size, offset)   _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
84#define efree_rel(ptr)                          _efree((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
85#define ecalloc_rel(nmemb, size)                _ecalloc((nmemb), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
86#define erealloc_rel(ptr, size)                 _erealloc((ptr), (size), 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
87#define erealloc_recoverable_rel(ptr, size)     _erealloc((ptr), (size), 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
88#define safe_erealloc_rel(ptr, nmemb, size, offset) _safe_erealloc((ptr), (nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
89#define estrdup_rel(s)                          _estrdup((s) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
90#define estrndup_rel(s, length)                 _estrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
91#define zend_mem_block_size_rel(ptr)            _zend_mem_block_size((ptr) TSRMLS_CC ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
92
93inline static void * __zend_malloc(size_t len)
94{
95    void *tmp = malloc(len);
96    if (tmp) {
97        return tmp;
98    }
99    fprintf(stderr, "Out of memory\n");
100    exit(1);
101}
102
103inline static void * __zend_calloc(size_t nmemb, size_t len)
104{
105    void *tmp = _safe_malloc(nmemb, len, 0);
106    memset(tmp, 0, nmemb * len);
107    return tmp;
108}
109
110inline static void * __zend_realloc(void *p, size_t len)
111{
112    p = realloc(p, len);
113    if (p) {
114        return p;
115    }
116    fprintf(stderr, "Out of memory\n");
117    exit(1);
118}
119
120
121/* Selective persistent/non persistent allocation macros */
122#define pemalloc(size, persistent) ((persistent)?__zend_malloc(size):emalloc(size))
123#define safe_pemalloc(nmemb, size, offset, persistent)  ((persistent)?_safe_malloc(nmemb, size, offset):safe_emalloc(nmemb, size, offset))
124#define pefree(ptr, persistent)  ((persistent)?free(ptr):efree(ptr))
125#define pecalloc(nmemb, size, persistent) ((persistent)?__zend_calloc((nmemb), (size)):ecalloc((nmemb), (size)))
126#define perealloc(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc((ptr), (size)))
127#define safe_perealloc(ptr, nmemb, size, offset, persistent)    ((persistent)?_safe_realloc((ptr), (nmemb), (size), (offset)):safe_erealloc((ptr), (nmemb), (size), (offset)))
128#define perealloc_recoverable(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc_recoverable((ptr), (size)))
129#define pestrdup(s, persistent) ((persistent)?strdup(s):estrdup(s))
130#define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
131
132#define pemalloc_rel(size, persistent) ((persistent)?__zend_malloc(size):emalloc_rel(size))
133#define pefree_rel(ptr, persistent) ((persistent)?free(ptr):efree_rel(ptr))
134#define pecalloc_rel(nmemb, size, persistent) ((persistent)?__zend_calloc((nmemb), (size)):ecalloc_rel((nmemb), (size)))
135#define perealloc_rel(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc_rel((ptr), (size)))
136#define perealloc_recoverable_rel(ptr, size, persistent) ((persistent)?__zend_realloc((ptr), (size)):erealloc_recoverable_rel((ptr), (size)))
137#define pestrdup_rel(s, persistent) ((persistent)?strdup(s):estrdup_rel(s))
138
139#define safe_estrdup(ptr)  ((ptr)?(estrdup(ptr)):STR_EMPTY_ALLOC())
140#define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):STR_EMPTY_ALLOC())
141
142ZEND_API int zend_set_memory_limit(size_t memory_limit TSRMLS_DC);
143
144ZEND_API void start_memory_manager(TSRMLS_D);
145ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC);
146ZEND_API int is_zend_mm(TSRMLS_D);
147
148#if ZEND_DEBUG
149ZEND_API int _mem_block_check(void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
150ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
151void zend_debug_alloc_output(char *format, ...);
152#define mem_block_check(ptr, silent) _mem_block_check(ptr, silent ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
153#define full_mem_check(silent) _full_mem_check(silent ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
154#else
155#define mem_block_check(type, ptr, silent)
156#define full_mem_check(silent)
157#endif
158
159ZEND_API size_t zend_memory_usage(int real_usage TSRMLS_DC);
160ZEND_API size_t zend_memory_peak_usage(int real_usage TSRMLS_DC);
161
162END_EXTERN_C()
163
164/* fast cache for zval's */
165#define ALLOC_ZVAL(z)   \
166    (z) = (zval *) emalloc(sizeof(zval))
167
168#define FREE_ZVAL(z)    \
169    efree_rel(z)
170
171#define ALLOC_ZVAL_REL(z)   \
172    (z) = (zval *) emalloc_rel(sizeof(zval))
173
174#define FREE_ZVAL_REL(z)    \
175    efree_rel(z)
176
177/* fast cache for HashTables */
178#define ALLOC_HASHTABLE(ht) \
179    (ht) = (HashTable *) emalloc(sizeof(HashTable))
180
181#define FREE_HASHTABLE(ht)  \
182    efree(ht)
183
184#define ALLOC_HASHTABLE_REL(ht) \
185    (ht) = (HashTable *) emalloc_rel(sizeof(HashTable))
186
187#define FREE_HASHTABLE_REL(ht)  \
188    efree_rel(ht)
189
190/* Heap functions */
191typedef struct _zend_mm_heap zend_mm_heap;
192
193ZEND_API zend_mm_heap *zend_mm_startup(void);
194ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC);
195ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
196ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
197ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
198ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
199
200#define zend_mm_alloc(heap, size)           _zend_mm_alloc((heap), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
201#define zend_mm_free(heap, p)               _zend_mm_free((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
202#define zend_mm_realloc(heap, p, size)      _zend_mm_realloc((heap), (p), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
203#define zend_mm_block_size(heap, p)         _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
204
205#define zend_mm_alloc_rel(heap, size)       _zend_mm_alloc((heap), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
206#define zend_mm_free_rel(heap, p)           _zend_mm_free((heap), (p) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
207#define zend_mm_realloc_rel(heap, p, size)  _zend_mm_realloc((heap), (p), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
208#define zend_mm_block_size_rel(heap, p)     _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
209
210/* Heaps with user defined storage */
211typedef struct _zend_mm_storage zend_mm_storage;
212
213typedef struct _zend_mm_segment {
214    size_t  size;
215    struct _zend_mm_segment *next_segment;
216} zend_mm_segment;
217
218typedef struct _zend_mm_mem_handlers {
219    const char *name;
220    zend_mm_storage* (*init)(void *params);
221    void (*dtor)(zend_mm_storage *storage);
222    void (*compact)(zend_mm_storage *storage);
223    zend_mm_segment* (*_alloc)(zend_mm_storage *storage, size_t size);
224    zend_mm_segment* (*_realloc)(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size);
225    void (*_free)(zend_mm_storage *storage, zend_mm_segment *ptr);
226} zend_mm_mem_handlers;
227
228struct _zend_mm_storage {
229    const zend_mm_mem_handlers *handlers;
230    void *data;
231};
232
233ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params);
234ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap TSRMLS_DC);
235ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap);
236
237ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
238                                          void* (*_malloc)(size_t),
239                                          void  (*_free)(void*),
240                                          void* (*_realloc)(void*, size_t));
241
242#endif
243
244/*
245 * Local variables:
246 * tab-width: 4
247 * c-basic-offset: 4
248 * indent-tabs-mode: t
249 * End:
250 */
251