mysqlnd_block_alloc.c [plain text]
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_block_alloc.h"
#include "mysqlnd_debug.h"
#include "mysqlnd_priv.h"
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) {
if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) {
pool->free_size += chunk->size;
}
pool->refcount--;
} else {
mnd_free(chunk->ptr);
}
mnd_free(chunk);
DBG_VOID_RETURN;
}
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;
if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) {
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;
pool->refcount--;
} else {
pool->free_size += (chunk->size - size);
}
} else {
if (chunk->size >= size) {
;
} 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;
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);
}
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;
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);
pool->free_size -= size;
}
}
DBG_RETURN(chunk);
}
PHPAPI MYSQLND_MEMORY_POOL *
mysqlnd_mempool_create(size_t arena_size TSRMLS_DC)
{
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;
ret->arena = mnd_malloc(ret->arena_size);
if (!ret->arena) {
mysqlnd_mempool_destroy(ret TSRMLS_CC);
ret = NULL;
}
}
DBG_RETURN(ret);
}
PHPAPI void
mysqlnd_mempool_destroy(MYSQLND_MEMORY_POOL * pool TSRMLS_DC)
{
DBG_ENTER("mysqlnd_mempool_destroy");
mnd_free(pool->arena);
mnd_free(pool);
DBG_VOID_RETURN;
}