summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_alloc.c1
-rw-r--r--Zend/zend_mm.c28
-rw-r--r--Zend/zend_mm.h5
3 files changed, 28 insertions, 6 deletions
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 8c4e3e187e..3e898c1174 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -462,6 +462,7 @@ ZEND_API void shutdown_memory_manager(int silent, int clean_cache TSRMLS_DC)
zend_fast_cache_list_entry *fast_cache_list_entry, *next_fast_cache_list_entry;
#if ZEND_MM
+ zend_mm_shutdown(&AG(mm_heap));
return;
#elif defined(ZEND_WIN32) && !ZEND_DEBUG
if (clean_cache && AG(memory_heap)) {
diff --git a/Zend/zend_mm.c b/Zend/zend_mm.c
index d39baefb8e..d5de6e5d86 100644
--- a/Zend/zend_mm.c
+++ b/Zend/zend_mm.c
@@ -48,6 +48,7 @@ typedef union _mm_align_test {
#define ZEND_MM_ALIGNED_SIZE(size) (size+(((ZEND_MM_ALIGNMENT-size)%ZEND_MM_ALIGNMENT+ZEND_MM_ALIGNMENT)%ZEND_MM_ALIGNMENT))
#define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block))
#define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_free_block))
+#define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment))
/* Memory calculations */
@@ -87,16 +88,24 @@ static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_fre
zend_bool zend_mm_add_memory_block(zend_mm_heap *heap, size_t block_size)
{
+ /* We need to make sure that block_size is big enough for the minimum segment size */
zend_mm_free_block *mm_block;
zend_mm_block *guard_block;
+ zend_mm_segment *segment;
/* align block size downwards */
block_size -= block_size % ZEND_MM_ALIGNMENT;
- mm_block = (zend_mm_free_block *) malloc(block_size);
- if (!mm_block) {
+ segment = (zend_mm_segment *) malloc(block_size);
+ if (!segment) {
return 1;
}
+ segment->next_segment = heap->segments_list;
+ heap->segments_list = segment;
+
+ block_size -= ZEND_MM_ALIGNED_SEGMENT_SIZE;
+ mm_block = (zend_mm_free_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE);
+
mm_block->size = block_size - ZEND_MM_ALIGNED_FREE_HEADER_SIZE; /* keep one guard block in the end */
mm_block->type = ZEND_MM_FREE_BLOCK;
mm_block->prev_size = 0; /* Size is always at least ZEND_MM_ALIGNED_HEADER_SIZE big (>0) so 0 is OK */
@@ -119,16 +128,23 @@ zend_bool zend_mm_add_memory_block(zend_mm_heap *heap, size_t block_size)
*/
zend_bool zend_mm_startup(zend_mm_heap *heap, size_t block_size)
{
- block_size -= block_size % ZEND_MM_ALIGNMENT;
heap->block_size = block_size;
heap->free_list = NULL;
-
+ heap->segments_list = NULL;
return zend_mm_add_memory_block(heap, block_size);
}
void zend_mm_shutdown(zend_mm_heap *heap)
{
+ zend_mm_segment *segment = heap->segments_list;
+ zend_mm_segment *prev;
+
+ while (segment) {
+ prev = segment;
+ segment = segment->next_segment;
+ free(prev);
+ }
}
void *zend_mm_alloc(zend_mm_heap *heap, size_t size)
@@ -149,9 +165,9 @@ void *zend_mm_alloc(zend_mm_heap *heap, size_t size)
}
}
if (!best_fit) {
- if (true_size > (heap->block_size - ZEND_MM_ALIGNED_HEADER_SIZE)) {
+ if (true_size > (heap->block_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_FREE_HEADER_SIZE)) {
/* Make sure we add a memory block which is big enough */
- zend_mm_add_memory_block(heap, true_size + ZEND_MM_ALIGNED_HEADER_SIZE);
+ zend_mm_add_memory_block(heap, true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_FREE_HEADER_SIZE);
} else {
zend_mm_add_memory_block(heap, heap->block_size);
}
diff --git a/Zend/zend_mm.h b/Zend/zend_mm.h
index eacaf4e328..5873b27cd2 100644
--- a/Zend/zend_mm.h
+++ b/Zend/zend_mm.h
@@ -41,9 +41,14 @@ typedef struct _zend_mm_free_block {
struct _zend_mm_free_block *next_free_block;
} zend_mm_free_block;
+typedef struct _zend_mm_segment {
+ struct _zend_mm_segment *next_segment;
+} zend_mm_segment;
+
typedef struct _zend_mm_heap {
/* Head of free list */
zend_mm_free_block *free_list;
+ zend_mm_segment *segments_list;
size_t block_size;
} zend_mm_heap;