diff options
author | Anatol Belski <ab@php.net> | 2014-10-15 08:32:54 +0200 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2014-10-15 08:32:54 +0200 |
commit | 382f95e6127d52b079d172ccd017cf306402e015 (patch) | |
tree | dcc5d8f6f2b1390a3d93a5be5994d625d260bfd9 /Zend/zend_alloc.c | |
parent | 766eb0103fe8f59c00ddadc5c5767093ee35b2e8 (diff) | |
parent | 01d17228dc62ea30b7ad25835f049ccd1998b5f2 (diff) | |
download | php-git-382f95e6127d52b079d172ccd017cf306402e015.tar.gz |
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: (25 commits)
Fix return code (merges are hard :( )
fix bad merge
Fix bug #68113 (Heap corruption in exif_thumbnail())
Fix bug #68089 - do not accept options with embedded \0
Fixed bug #68044: Integer overflow in unserialize() (32-bits only)
Fix bug #68027 - fix date parsing in XMLRPC lib
Fix bug #68113 (Heap corruption in exif_thumbnail())
Fix bug #68089 - do not accept options with embedded \0
Fixed bug #68044: Integer overflow in unserialize() (32-bits only)
Fix bug #68027 - fix date parsing in XMLRPC lib
Fix bug #68113 (Heap corruption in exif_thumbnail())
Fix bug #68089 - do not accept options with embedded \0
Fixed bug #68044: Integer overflow in unserialize() (32-bits only)
Fix bug #68027 - fix date parsing in XMLRPC lib
Fixed bug #68128
Added API function to retrive current custom heap handlers
update NEWS and UPGRADING
Allow to substitute storage layer in memory manager.
Upated NEWS
Address issues raised by @nikic
...
Diffstat (limited to 'Zend/zend_alloc.c')
-rw-r--r-- | Zend/zend_alloc.c | 173 |
1 files changed, 159 insertions, 14 deletions
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index aea04d82f0..fb4d3b35e1 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -119,6 +119,9 @@ # define ZEND_MM_CUSTOM 1 /* support for custom memory allocator */ /* USE_ZEND_ALLOC=0 may switch to system malloc() */ #endif +#ifndef ZEND_MM_STORAGE +# define ZEND_MM_STORAGE 1 /* support for custom memory storage */ +#endif #ifndef ZEND_MM_ERROR # define ZEND_MM_ERROR 1 /* report system errors */ #endif @@ -217,6 +220,9 @@ struct _zend_mm_heap { #if ZEND_MM_CUSTOM int use_custom_heap; #endif +#if ZEND_MM_STORAGE + zend_mm_storage *storage; +#endif #if ZEND_MM_STAT size_t size; /* current memory usage */ size_t peak; /* peak memory usage */ @@ -707,7 +713,7 @@ static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitse /* Chunks */ /**********/ -static void *zend_mm_chunk_alloc(size_t size, size_t alignment) +static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment) { void *ptr = zend_mm_mmap(size); @@ -751,6 +757,40 @@ static void *zend_mm_chunk_alloc(size_t size, size_t alignment) } } +static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignment) +{ +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + void *ptr = heap->storage->chunk_alloc(heap->storage, size, alignment); + ZEND_ASSERT(((zend_uintptr_t)((char*)ptr + (alignment-1)) & (alignment-1)) == (zend_uintptr_t)ptr); + return ptr; + } +#endif + return zend_mm_chunk_alloc_int(size, alignment); +} + +static void zend_mm_chunk_free(zend_mm_heap *heap, void *addr, size_t size) +{ +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + heap->storage->chunk_free(heap->storage, addr, size); + return; + } +#endif + zend_mm_munmap(addr, size); +} + +static void zend_mm_chunk_truncate(zend_mm_heap *heap, void *addr, size_t old_size, size_t new_size) +{ +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + heap->storage->chunk_truncate(heap->storage, addr, old_size, new_size); + return; + } +#endif + zend_mm_munmap((char*)addr + new_size, old_size - new_size); +} + static zend_always_inline void zend_mm_chunk_init(zend_mm_heap *heap, zend_mm_chunk *chunk) { chunk->heap = heap; @@ -928,7 +968,7 @@ not_found: } } #endif - chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); + chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(heap, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); if (UNEXPECTED(chunk == NULL)) { /* insufficient memory */ #if !ZEND_MM_LIMIT @@ -1019,11 +1059,11 @@ static void zend_mm_free_pages(zend_mm_heap *heap, zend_mm_chunk *chunk, int pag heap->real_size -= ZEND_MM_CHUNK_SIZE; #endif if (!heap->cached_chunks || chunk->num > heap->cached_chunks->num) { - zend_mm_munmap(chunk, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, chunk, ZEND_MM_CHUNK_SIZE); } else { //TODO: select the best chunk to delete??? chunk->next = heap->cached_chunks->next; - zend_mm_munmap(heap->cached_chunks, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, heap->cached_chunks, ZEND_MM_CHUNK_SIZE); heap->cached_chunks = chunk; } } @@ -1355,7 +1395,7 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN #ifndef _WIN32 } else if (new_size < old_size) { /* unmup tail */ - zend_mm_munmap((char*)ptr + new_size, old_size - new_size); + zend_mm_chunk_truncate(heap, ptr, old_size, new_size); #if ZEND_MM_STAT || ZEND_MM_LIMIT heap->real_size -= old_size - new_size; #endif @@ -1607,7 +1647,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D } } #endif - ptr = zend_mm_chunk_alloc(new_size, ZEND_MM_CHUNK_SIZE); + ptr = zend_mm_chunk_alloc(heap, new_size, ZEND_MM_CHUNK_SIZE); if (UNEXPECTED(ptr == NULL)) { /* insufficient memory */ #if !ZEND_MM_LIMIT @@ -1649,7 +1689,7 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE) == 0, "zend_mm_heap corrupted"); size = zend_mm_del_huge_block(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - zend_mm_munmap(ptr, size); + zend_mm_chunk_free(heap, ptr, size); #if ZEND_MM_STAT || ZEND_MM_LIMIT heap->real_size -= size; #endif @@ -1662,9 +1702,9 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE /* Initialization */ /******************/ -zend_mm_heap *zend_mm_init(void) +static zend_mm_heap *zend_mm_init(void) { - zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc_int(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); zend_mm_heap *heap; if (UNEXPECTED(chunk == NULL)) { @@ -1707,6 +1747,9 @@ zend_mm_heap *zend_mm_init(void) #if ZEND_MM_CUSTOM heap->use_custom_heap = 0; #endif +#if ZEND_MM_STORAGE + heap->storage = NULL; +#endif heap->huge_list = NULL; return heap; } @@ -1805,7 +1848,7 @@ static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC) } list = list->next; - zend_mm_munmap(q->ptr, q->size); + zend_mm_chunk_free(heap, q->ptr, q->size); zend_mm_free_heap(heap, q, NULL, 0, NULL, 0); } @@ -1904,7 +1947,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC) while (list) { zend_mm_huge_list *q = list; list = list->next; - zend_mm_munmap(q->ptr, q->size); + zend_mm_chunk_free(heap, q->ptr, q->size); } /* move all chunks except of the first one into the cache */ @@ -1923,10 +1966,20 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC) while (heap->cached_chunks) { p = heap->cached_chunks; heap->cached_chunks = p->next; - zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE); } /* free the first chunk */ - zend_mm_munmap(heap->main_chunk, ZEND_MM_CHUNK_SIZE); +#if ZEND_MM_STORAGE + if (UNEXPECTED(heap->storage)) { + zend_mm_storage *storage = heap->storage; + zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); + storage->dtor(storage); + } else { + zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); + } +#else + zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); +#endif } else { zend_mm_heap old_heap; @@ -1936,7 +1989,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC) heap->cached_chunks) { p = heap->cached_chunks; heap->cached_chunks = p->next; - zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE); heap->cached_chunks_count--; } /* clear cached chunks */ @@ -2343,6 +2396,98 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, #endif } +ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, + void* (**_malloc)(size_t), + void (**_free)(void*), + void* (**_realloc)(void*, size_t)) +{ +#if ZEND_MM_CUSTOM + zend_mm_heap *_heap = (zend_mm_heap*)heap; + + if (heap->use_custom_heap) { + *_malloc = _heap->_malloc; + *_free = _heap->_free; + *_realloc = _heap->_realloc; + } else { + *_malloc = NULL; + *_free = NULL; + *_realloc = NULL; + } +#else + *_malloc = NULL; + *_free = NULL; + *_realloc = NULL; +#endif +} + +ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap) +{ +#if ZEND_MM_CUSTOM + return heap->storage; +#else + return NULL +#endif +} + +ZEND_API zend_mm_heap *zend_mm_startup(void) +{ + return zend_mm_init(); +} + +ZEND_API zend_mm_heap *zend_mm_startup_ex(zend_mm_storage *storage) +{ +#if ZEND_MM_STORAGE + zend_mm_chunk *chunk = (zend_mm_chunk*)storage->chunk_alloc(storage, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE); + zend_mm_heap *heap; + + if (UNEXPECTED(chunk == NULL)) { +#if ZEND_MM_ERROR +#ifdef _WIN32 + stderr_last_error("Can't initialize heap"); +#else + fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno)); +#endif +#endif + return NULL; + } + heap = &chunk->heap_slot; + chunk->heap = heap; + chunk->next = chunk; + chunk->prev = chunk; + chunk->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE; + chunk->free_tail = ZEND_MM_FIRST_PAGE; + chunk->num = 0; + chunk->free_map[0] = (Z_L(1) << ZEND_MM_FIRST_PAGE) - 1; + chunk->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE); + heap->main_chunk = chunk; + heap->cached_chunks = NULL; + heap->chunks_count = 1; + heap->peak_chunks_count = 1; + heap->cached_chunks_count = 0; + heap->avg_chunks_count = 1.0; +#if ZEND_MM_STAT || ZEND_MM_LIMIT + heap->real_size = ZEND_MM_CHUNK_SIZE; +#endif +#if ZEND_MM_STAT + heap->real_peak = ZEND_MM_CHUNK_SIZE; + heap->size = 0; + heap->peak = 0; +#endif +#if ZEND_MM_LIMIT + heap->limit = (Z_L(-1) >> Z_L(1)); + heap->overflow = 0; +#endif +#if ZEND_MM_CUSTOM + heap->use_custom_heap = 0; +#endif + heap->storage = storage; + heap->huge_list = NULL; + return heap; +#else + return NULL; +#endif +} + /* * Local variables: * tab-width: 4 |