Bug #51155 (Unreasonable non-emalloc allocations of memory)

This commit is contained in:
Dmitry Stogov 2010-10-04 15:50:47 +00:00
parent 026da7d4a0
commit 656f1fb271

View file

@ -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) {