/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 2006-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Georg Richter <georg@mysql.com> | | Andrey Hristov <andrey@mysql.com> | | Ulf Wendel <uwendel@mysql.com> | +----------------------------------------------------------------------+ */ /* $Id$ */ #include "php.h" #include "mysqlnd.h" #include "mysqlnd_block_alloc.h" #include "mysqlnd_debug.h" #include "mysqlnd_priv.h" /* {{{ mysqlnd_mempool_free_chunk */ static void mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk TSRMLS_DC) { MYSQLND_MEMORY_POOL * pool = chunk->pool; DBG_ENTER("mysqlnd_mempool_free_chunk"); if (chunk->from_pool) { /* Try to back-off and guess if this is the last block allocated */ if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) { /* This was the last allocation. Lucky us, we can free a bit of memory from the pool. Next time we will return from the same ptr. */ pool->free_size += chunk->size; } pool->refcount--; } else { mnd_free(chunk->ptr); } mnd_free(chunk); DBG_VOID_RETURN; } /* }}} */ /* {{{ mysqlnd_mempool_resize_chunk */ static enum_func_status mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size TSRMLS_DC) { DBG_ENTER("mysqlnd_mempool_resize_chunk"); if (chunk->from_pool) { MYSQLND_MEMORY_POOL * pool = chunk->pool; /* Try to back-off and guess if this is the last block allocated */ if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) { /* This was the last allocation. Lucky us, we can free a bit of memory from the pool. Next time we will return from the same ptr. */ if ((chunk->size + pool->free_size) < size) { zend_uchar *new_ptr; new_ptr = mnd_malloc(size); if (!new_ptr) { DBG_RETURN(FAIL); } memcpy(new_ptr, chunk->ptr, chunk->size); chunk->ptr = new_ptr; pool->free_size += chunk->size; chunk->size = size; chunk->pool = NULL; /* now we have no pool memory */ pool->refcount--; } else { /* If the chunk is > than asked size then free_memory increases, otherwise decreases*/ pool->free_size += (chunk->size - size); } } else { /* Not last chunk, if the user asks for less, give it to him */ if (chunk->size >= size) { ; /* nop */ } else { zend_uchar *new_ptr; new_ptr = mnd_malloc(size); if (!new_ptr) { DBG_RETURN(FAIL); } memcpy(new_ptr, chunk->ptr, chunk->size); chunk->ptr = new_ptr; chunk->size = size; chunk->pool = NULL; /* now we have non-pool memory */ pool->refcount--; } } } else { zend_uchar *new_ptr = mnd_realloc(chunk->ptr, size); if (!new_ptr) { DBG_RETURN(FAIL); } chunk->ptr = new_ptr; } DBG_RETURN(PASS); } /* }}} */ /* {{{ mysqlnd_mempool_get_chunk */ static MYSQLND_MEMORY_POOL_CHUNK * mysqlnd_mempool_get_chunk(MYSQLND_MEMORY_POOL * pool, unsigned int size TSRMLS_DC) { MYSQLND_MEMORY_POOL_CHUNK *chunk = NULL; DBG_ENTER("mysqlnd_mempool_get_chunk"); chunk = mnd_malloc(sizeof(MYSQLND_MEMORY_POOL_CHUNK)); if (chunk) { chunk->free_chunk = mysqlnd_mempool_free_chunk; chunk->resize_chunk = mysqlnd_mempool_resize_chunk; chunk->size = size; /* Should not go over MYSQLND_MAX_PACKET_SIZE, since we expect non-arena memory in mysqlnd_wireprotocol.c . We realloc the non-arena memory. */ chunk->pool = pool; if (size > pool->free_size) { chunk->from_pool = FALSE; chunk->ptr = mnd_malloc(size); if (!chunk->ptr) { chunk->free_chunk(chunk TSRMLS_CC); chunk = NULL; } } else { chunk->from_pool = TRUE; ++pool->refcount; chunk->ptr = pool->arena + (pool->arena_size - pool->free_size); /* Last step, update free_size */ pool->free_size -= size; } } DBG_RETURN(chunk); } /* }}} */ /* {{{ mysqlnd_mempool_create */ PHPAPI MYSQLND_MEMORY_POOL * mysqlnd_mempool_create(size_t arena_size TSRMLS_DC) { /* We calloc, because we free(). We don't mnd_calloc() for a reason. */ MYSQLND_MEMORY_POOL * ret = mnd_calloc(1, sizeof(MYSQLND_MEMORY_POOL)); DBG_ENTER("mysqlnd_mempool_create"); if (ret) { ret->get_chunk = mysqlnd_mempool_get_chunk; ret->free_size = ret->arena_size = arena_size ? arena_size : 0; ret->refcount = 0; /* OOM ? */ ret->arena = mnd_malloc(ret->arena_size); if (!ret->arena) { mysqlnd_mempool_destroy(ret TSRMLS_CC); ret = NULL; } } DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_mempool_destroy */ PHPAPI void mysqlnd_mempool_destroy(MYSQLND_MEMORY_POOL * pool TSRMLS_DC) { DBG_ENTER("mysqlnd_mempool_destroy"); /* mnd_free will reference LOCK_access and might crash, depending on the caller...*/ mnd_free(pool->arena); mnd_free(pool); DBG_VOID_RETURN; } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
mysql_float_to_double.h | File | 2.08 KB | 0644 |
|
mysqlnd.c | File | 100.11 KB | 0644 |
|
mysqlnd.h | File | 17.55 KB | 0644 |
|
mysqlnd_alloc.c | File | 22 KB | 0644 |
|
mysqlnd_alloc.h | File | 5.76 KB | 0644 |
|
mysqlnd_auth.c | File | 22.62 KB | 0644 |
|
mysqlnd_block_alloc.c | File | 5.76 KB | 0644 |
|
mysqlnd_block_alloc.h | File | 1.65 KB | 0644 |
|
mysqlnd_bt.c | File | 6.95 KB | 0644 |
|
mysqlnd_charset.c | File | 33.08 KB | 0644 |
|
mysqlnd_charset.h | File | 2.39 KB | 0644 |
|
mysqlnd_debug.c | File | 24.29 KB | 0644 |
|
mysqlnd_debug.h | File | 9.93 KB | 0644 |
|
mysqlnd_driver.c | File | 10.02 KB | 0644 |
|
mysqlnd_enum_n_def.h | File | 18.98 KB | 0644 |
|
mysqlnd_ext_plugin.c | File | 8.69 KB | 0644 |
|
mysqlnd_ext_plugin.h | File | 5.06 KB | 0644 |
|
mysqlnd_loaddata.c | File | 7.5 KB | 0644 |
|
mysqlnd_net.c | File | 40.7 KB | 0644 |
|
mysqlnd_net.h | File | 1.77 KB | 0644 |
|
mysqlnd_plugin.c | File | 6.09 KB | 0644 |
|
mysqlnd_priv.h | File | 8.77 KB | 0644 |
|
mysqlnd_ps.c | File | 73.23 KB | 0644 |
|
mysqlnd_ps_codec.c | File | 31.21 KB | 0644 |
|
mysqlnd_result.c | File | 69.74 KB | 0644 |
|
mysqlnd_result.h | File | 2.09 KB | 0644 |
|
mysqlnd_result_meta.c | File | 13.5 KB | 0644 |
|
mysqlnd_reverse_api.c | File | 3.03 KB | 0644 |
|
mysqlnd_reverse_api.h | File | 2.06 KB | 0644 |
|
mysqlnd_statistics.c | File | 11.79 KB | 0644 |
|
mysqlnd_statistics.h | File | 7.7 KB | 0644 |
|
mysqlnd_structs.h | File | 55.79 KB | 0644 |
|
mysqlnd_wireprotocol.c | File | 82.77 KB | 0644 |
|
mysqlnd_wireprotocol.h | File | 10.22 KB | 0644 |
|
php_mysqlnd.c | File | 12.03 KB | 0644 |
|