diff -uNr php5.3-201201270830/Zend/zend_alloc.c php5.3-new/Zend/zend_alloc.c --- php5.3-201201270830/Zend/zend_alloc.c Wed Jan 4 14:31:31 2012 +++ php5.3-new/Zend/zend_alloc.c Sat Jan 28 00:48:49 2012 @@ -439,6 +439,7 @@ 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; @@ -459,6 +460,10 @@ 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; @@ -715,23 +720,6 @@ #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; @@ -858,12 +846,45 @@ 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; @@ -888,6 +909,7 @@ 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) @@ -1126,6 +1148,7 @@ } } 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; @@ -1578,6 +1601,13 @@ zend_mm_segment *prev; int internal; + if (!heap->use_zend_alloc) { + if (full_shutdown) { + free(heap); + } + return; + } + if (heap->reserve) { #if ZEND_DEBUG if (!silent) { @@ -1642,27 +1672,63 @@ internal = heap->internal; storage = heap->storage; segment = heap->segments_list; - while (segment) { - prev = segment; - segment = segment->next_segment; - ZEND_MM_STORAGE_FREE(prev); - } if (full_shutdown) { + while (segment) { + prev = segment; + segment = segment->next_segment; + ZEND_MM_STORAGE_FREE(prev); + } + heap->segments_list = NULL; storage->handlers->dtor(storage); if (!internal) { free(heap); } } else { + if (segment) { +#ifndef ZEND_WIN32 + if (heap->reserve_size) { + while (segment->next_segment) { + prev = segment; + segment = segment->next_segment; + ZEND_MM_STORAGE_FREE(prev); + } + heap->segments_list = segment; + } else { +#endif + do { + prev = segment; + segment = segment->next_segment; + ZEND_MM_STORAGE_FREE(prev); + } while (segment); + heap->segments_list = NULL; +#ifndef ZEND_WIN32 + } +#endif + } if (heap->compact_size && heap->real_peak > heap->compact_size) { storage->handlers->compact(storage); } - heap->segments_list = NULL; 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) { + /* mark segment as a free block */ + zend_mm_free_block *b = (zend_mm_free_block*)((char*)heap->segments_list + ZEND_MM_ALIGNED_SEGMENT_SIZE); + size_t block_size = heap->segments_list->size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE; + + ZEND_MM_MARK_FIRST_BLOCK(b); + ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(b, block_size)); + ZEND_MM_BLOCK(b, ZEND_MM_FREE_BLOCK, block_size); + zend_mm_add_to_free_list(heap, b); + } if (heap->reserve_size) { heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); } @@ -1817,6 +1883,8 @@ zend_mm_segment *segment; int keep_rest = 0; + HANDLE_BLOCK_INTERRUPTIONS(); + if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) { size_t index = ZEND_MM_BUCKET_INDEX(true_size); size_t bitmap; @@ -1836,6 +1904,7 @@ heap->cached -= true_size; ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED); ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0); + HANDLE_UNBLOCK_INTERRUPTIONS(); return ZEND_MM_DATA_OF(best_fit); } #if ZEND_MM_CACHE_STAT @@ -1889,8 +1958,6 @@ segment_size = heap->block_size; } - HANDLE_BLOCK_INTERRUPTIONS(); - if (segment_size < true_size || heap->real_size + segment_size > heap->limit) { /* Memory limit overflow */ @@ -1912,8 +1979,8 @@ #if ZEND_MM_CACHE zend_mm_free_cache(heap); #endif - HANDLE_UNBLOCK_INTERRUPTIONS(); out_of_memory: + HANDLE_UNBLOCK_INTERRUPTIONS(); #if ZEND_DEBUG zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else @@ -1941,7 +2008,6 @@ } else { zend_mm_finished_searching_for_block: /* remove from free list */ - HANDLE_BLOCK_INTERRUPTIONS(); ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED); ZEND_MM_CHECK_COOKIE(best_fit); ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit); @@ -1994,6 +2060,8 @@ return; } + HANDLE_BLOCK_INTERRUPTIONS(); + mm_block = ZEND_MM_HEADER_OF(p); size = ZEND_MM_BLOCK_SIZE(mm_block); ZEND_MM_CHECK_PROTECTION(mm_block); @@ -2016,12 +2084,11 @@ heap->cache_stat[index].max_count = heap->cache_stat[index].count; } #endif + HANDLE_UNBLOCK_INTERRUPTIONS(); return; } #endif - HANDLE_BLOCK_INTERRUPTIONS(); - heap->size -= size; next_block = ZEND_MM_BLOCK_AT(mm_block, size); @@ -2055,6 +2122,9 @@ if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) { return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } + + HANDLE_BLOCK_INTERRUPTIONS(); + mm_block = ZEND_MM_HEADER_OF(p); true_size = ZEND_MM_TRUE_SIZE(size); orig_size = ZEND_MM_BLOCK_SIZE(mm_block); @@ -2070,7 +2140,6 @@ if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) { zend_mm_free_block *new_free_block; - HANDLE_BLOCK_INTERRUPTIONS(); next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size); if (ZEND_MM_IS_FREE_BLOCK(next_block)) { remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block); @@ -2086,9 +2155,9 @@ /* add the new free block to the free list */ zend_mm_add_to_free_list(heap, new_free_block); heap->size += (true_size - orig_size); - HANDLE_UNBLOCK_INTERRUPTIONS(); } ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0); + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2131,6 +2200,7 @@ } #endif + HANDLE_UNBLOCK_INTERRUPTIONS(); return ptr; } } @@ -2145,7 +2215,6 @@ size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block); size_t remaining_size = block_size - true_size; - HANDLE_BLOCK_INTERRUPTIONS(); zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block); if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) { @@ -2176,7 +2245,6 @@ return p; } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) { - HANDLE_BLOCK_INTERRUPTIONS(); zend_mm_remove_from_free_list(heap, (zend_mm_free_block *) next_block); goto realloc_segment; } @@ -2187,7 +2255,6 @@ size_t block_size; size_t remaining_size; - HANDLE_BLOCK_INTERRUPTIONS(); realloc_segment: /* segment size, size of block and size of guard block */ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) { @@ -2220,8 +2287,8 @@ #if ZEND_MM_CACHE zend_mm_free_cache(heap); #endif - HANDLE_UNBLOCK_INTERRUPTIONS(); out_of_memory: + HANDLE_UNBLOCK_INTERRUPTIONS(); #if ZEND_DEBUG zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size); #else @@ -2285,6 +2352,7 @@ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE); #endif _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + HANDLE_UNBLOCK_INTERRUPTIONS(); return ptr; } @@ -2473,12 +2541,15 @@ ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { void *p; + HANDLE_BLOCK_INTERRUPTIONS(); p = _safe_emalloc(nmemb, size, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) { + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } memset(p, 0, size * nmemb); + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2487,12 +2558,16 @@ int length; char *p; + HANDLE_BLOCK_INTERRUPTIONS(); + length = strlen(s)+1; p = (char *) _emalloc(length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) { + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } memcpy(p, s, length); + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2500,12 +2575,16 @@ { char *p; + HANDLE_BLOCK_INTERRUPTIONS(); + p = (char *) _emalloc(length+1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); if (UNEXPECTED(p == NULL)) { + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } memcpy(p, s, length); p[length] = 0; + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2514,14 +2593,18 @@ { char *p; + HANDLE_BLOCK_INTERRUPTIONS(); + p = (char *) malloc(length+1); if (UNEXPECTED(p == NULL)) { + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } if (length) { memcpy(p, s, length); } p[length] = 0; + HANDLE_UNBLOCK_INTERRUPTIONS(); return p; } @@ -2564,17 +2647,17 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC) { - char *tmp; - alloc_globals->mm_heap = zend_mm_startup(); + char *tmp = getenv("USE_ZEND_ALLOC"); - tmp = getenv("USE_ZEND_ALLOC"); - if (tmp) { - alloc_globals->mm_heap->use_zend_alloc = zend_atoi(tmp, 0); - if (!alloc_globals->mm_heap->use_zend_alloc) { - alloc_globals->mm_heap->_malloc = malloc; - alloc_globals->mm_heap->_free = free; - alloc_globals->mm_heap->_realloc = realloc; - } + if (tmp && !zend_atoi(tmp, 0)) { + alloc_globals->mm_heap = malloc(sizeof(struct _zend_mm_heap)); + memset(alloc_globals->mm_heap, 0, sizeof(struct _zend_mm_heap)); + alloc_globals->mm_heap->use_zend_alloc = 0; + alloc_globals->mm_heap->_malloc = malloc; + alloc_globals->mm_heap->_free = free; + alloc_globals->mm_heap->_realloc = realloc; + } else { + alloc_globals->mm_heap = zend_mm_startup(); } } diff -uNr php5.3-201201270830/main/SAPI.c php5.3-new/main/SAPI.c --- php5.3-201201270830/main/SAPI.c Sat Jan 14 08:31:02 2012 +++ php5.3-new/main/SAPI.c Sat Jan 28 00:48:49 2012 @@ -79,7 +79,9 @@ #ifdef ZTS ts_allocate_id(&sapi_globals_id, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor); # ifdef PHP_WIN32 +# ifdef _ENABLE_PER_THREAD_LOCALE _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); +# endif # endif #else sapi_globals_ctor(&sapi_globals);