summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2010-10-04 15:50:47 +0000
committerDmitry Stogov <dmitry@php.net>2010-10-04 15:50:47 +0000
commit656f1fb2713abe2c5831056a977b2d7ba7b0dc5c (patch)
treee6340c4db66c0fc14654255865233e9937f8352a
parent026da7d4a081a143a6dc905c71a1a386c9ae503e (diff)
downloadphp-git-656f1fb2713abe2c5831056a977b2d7ba7b0dc5c.tar.gz
Bug #51155 (Unreasonable non-emalloc allocations of memory)
-rw-r--r--Zend/zend_alloc.c66
1 files 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) {