From 656f1fb2713abe2c5831056a977b2d7ba7b0dc5c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 4 Oct 2010 15:50:47 +0000 Subject: [PATCH] Bug #51155 (Unreasonable non-emalloc allocations of memory) --- Zend/zend_alloc.c | 66 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index d89cd247a9..7bc531a86e 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -435,6 +435,7 @@ struct _zend_mm_heap { zend_mm_free_block *free_buckets[ZEND_MM_NUM_BUCKETS*2]; zend_mm_free_block *large_free_buckets[ZEND_MM_NUM_BUCKETS]; zend_mm_free_block *rest_buckets[2]; + int rest_count; #if ZEND_MM_CACHE_STAT struct { int count; @@ -455,6 +456,10 @@ struct _zend_mm_heap { sizeof(zend_mm_free_block*) * 2 - \ sizeof(zend_mm_small_free_block)) +#define ZEND_MM_REST_BLOCK ((zend_mm_free_block*)(zend_uintptr_t)(1)) + +#define ZEND_MM_MAX_REST_BLOCKS 16 + #if ZEND_MM_COOKIES static unsigned int _zend_mm_cookie = 0; @@ -711,23 +716,6 @@ static inline unsigned int zend_mm_low_bit(size_t _size) #endif } -static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) -{ - zend_mm_free_block *prev, *next; - - ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED); - - if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) { - mm_block->parent = NULL; - } - - prev = heap->rest_buckets[0]; - next = prev->next_free_block; - mm_block->prev_free_block = prev; - mm_block->next_free_block = next; - prev->next_free_block = next->prev_free_block = mm_block; -} - static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) { size_t size; @@ -854,12 +842,45 @@ subst_block: heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index); } } + } else if (UNEXPECTED(mm_block->parent == ZEND_MM_REST_BLOCK)) { + heap->rest_count--; } else if (UNEXPECTED(mm_block->parent != NULL)) { goto subst_block; } } } +static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) +{ + zend_mm_free_block *prev, *next; + + while (heap->rest_count >= ZEND_MM_MAX_REST_BLOCKS) { + zend_mm_free_block *p = heap->rest_buckets[1]; + + if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(p))) { + heap->rest_count--; + } + prev = p->prev_free_block; + next = p->next_free_block; + prev->next_free_block = next; + next->prev_free_block = prev; + zend_mm_add_to_free_list(heap, p); + } + + if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) { + mm_block->parent = ZEND_MM_REST_BLOCK; + heap->rest_count++; + } + + ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED); + + prev = heap->rest_buckets[0]; + next = prev->next_free_block; + mm_block->prev_free_block = prev; + mm_block->next_free_block = next; + prev->next_free_block = next->prev_free_block = mm_block; +} + static inline void zend_mm_init(zend_mm_heap *heap) { zend_mm_free_block* p; @@ -884,6 +905,7 @@ static inline void zend_mm_init(zend_mm_heap *heap) heap->large_free_buckets[i] = NULL; } heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap); + heap->rest_count = 0; } static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment) @@ -1116,6 +1138,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, } } mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap); + mm_heap->rest_count = 0; free(heap); heap = mm_heap; @@ -1674,8 +1697,13 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent storage->handlers->compact(storage); } zend_mm_init(heap); - heap->real_size = 0; - heap->real_peak = 0; + if (heap->segments_list) { + heap->real_size = heap->segments_list->size; + heap->real_peak = heap->segments_list->size; + } else { + heap->real_size = 0; + heap->real_peak = 0; + } heap->size = 0; heap->peak = 0; if (heap->segments_list) { -- 2.40.0