Annotation of embedaddon/php/ext/mysqlnd/mysqlnd_block_alloc.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 2006-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Georg Richter <georg@mysql.com> |
! 16: | Andrey Hristov <andrey@mysql.com> |
! 17: | Ulf Wendel <uwendel@mysql.com> |
! 18: +----------------------------------------------------------------------+
! 19: */
! 20:
! 21: /* $Id: mysqlnd_block_alloc.c 321634 2012-01-01 13:15:04Z felipe $ */
! 22:
! 23: #include "php.h"
! 24: #include "mysqlnd.h"
! 25: #include "mysqlnd_block_alloc.h"
! 26: #include "mysqlnd_debug.h"
! 27: #include "mysqlnd_priv.h"
! 28:
! 29:
! 30: /* {{{ mysqlnd_mempool_free_chunk */
! 31: static void
! 32: mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk TSRMLS_DC)
! 33: {
! 34: MYSQLND_MEMORY_POOL * pool = chunk->pool;
! 35: DBG_ENTER("mysqlnd_mempool_free_chunk");
! 36: if (chunk->from_pool) {
! 37: /* Try to back-off and guess if this is the last block allocated */
! 38: if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) {
! 39: /*
! 40: This was the last allocation. Lucky us, we can free
! 41: a bit of memory from the pool. Next time we will return from the same ptr.
! 42: */
! 43: pool->free_size += chunk->size;
! 44: }
! 45: pool->refcount--;
! 46: } else {
! 47: mnd_free(chunk->ptr);
! 48: }
! 49: mnd_free(chunk);
! 50: DBG_VOID_RETURN;
! 51: }
! 52: /* }}} */
! 53:
! 54:
! 55: /* {{{ mysqlnd_mempool_resize_chunk */
! 56: static enum_func_status
! 57: mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size TSRMLS_DC)
! 58: {
! 59: DBG_ENTER("mysqlnd_mempool_resize_chunk");
! 60: if (chunk->from_pool) {
! 61: MYSQLND_MEMORY_POOL * pool = chunk->pool;
! 62: /* Try to back-off and guess if this is the last block allocated */
! 63: if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) {
! 64: /*
! 65: This was the last allocation. Lucky us, we can free
! 66: a bit of memory from the pool. Next time we will return from the same ptr.
! 67: */
! 68: if ((chunk->size + pool->free_size) < size) {
! 69: zend_uchar *new_ptr;
! 70: new_ptr = mnd_malloc(size);
! 71: if (!new_ptr) {
! 72: DBG_RETURN(FAIL);
! 73: }
! 74: memcpy(new_ptr, chunk->ptr, chunk->size);
! 75: chunk->ptr = new_ptr;
! 76: pool->free_size += chunk->size;
! 77: chunk->size = size;
! 78: chunk->pool = NULL; /* now we have no pool memory */
! 79: pool->refcount--;
! 80: } else {
! 81: /* If the chunk is > than asked size then free_memory increases, otherwise decreases*/
! 82: pool->free_size += (chunk->size - size);
! 83: }
! 84: } else {
! 85: /* Not last chunk, if the user asks for less, give it to him */
! 86: if (chunk->size >= size) {
! 87: ; /* nop */
! 88: } else {
! 89: zend_uchar *new_ptr;
! 90: new_ptr = mnd_malloc(size);
! 91: if (!new_ptr) {
! 92: DBG_RETURN(FAIL);
! 93: }
! 94: memcpy(new_ptr, chunk->ptr, chunk->size);
! 95: chunk->ptr = new_ptr;
! 96: chunk->size = size;
! 97: chunk->pool = NULL; /* now we have non-pool memory */
! 98: pool->refcount--;
! 99: }
! 100: }
! 101: } else {
! 102: zend_uchar *new_ptr = mnd_realloc(chunk->ptr, size);
! 103: if (!new_ptr) {
! 104: DBG_RETURN(FAIL);
! 105: }
! 106: chunk->ptr = new_ptr;
! 107: }
! 108: DBG_RETURN(PASS);
! 109: }
! 110: /* }}} */
! 111:
! 112:
! 113: /* {{{ mysqlnd_mempool_get_chunk */
! 114: static
! 115: MYSQLND_MEMORY_POOL_CHUNK * mysqlnd_mempool_get_chunk(MYSQLND_MEMORY_POOL * pool, unsigned int size TSRMLS_DC)
! 116: {
! 117: MYSQLND_MEMORY_POOL_CHUNK *chunk = NULL;
! 118: DBG_ENTER("mysqlnd_mempool_get_chunk");
! 119:
! 120: chunk = mnd_malloc(sizeof(MYSQLND_MEMORY_POOL_CHUNK));
! 121: if (chunk) {
! 122: chunk->free_chunk = mysqlnd_mempool_free_chunk;
! 123: chunk->resize_chunk = mysqlnd_mempool_resize_chunk;
! 124: chunk->size = size;
! 125: /*
! 126: Should not go over MYSQLND_MAX_PACKET_SIZE, since we
! 127: expect non-arena memory in mysqlnd_wireprotocol.c . We
! 128: realloc the non-arena memory.
! 129: */
! 130: chunk->pool = pool;
! 131: if (size > pool->free_size) {
! 132: chunk->from_pool = FALSE;
! 133: chunk->ptr = mnd_malloc(size);
! 134: if (!chunk->ptr) {
! 135: chunk->free_chunk(chunk TSRMLS_CC);
! 136: chunk = NULL;
! 137: }
! 138: } else {
! 139: chunk->from_pool = TRUE;
! 140: ++pool->refcount;
! 141: chunk->ptr = pool->arena + (pool->arena_size - pool->free_size);
! 142: /* Last step, update free_size */
! 143: pool->free_size -= size;
! 144: }
! 145: }
! 146: DBG_RETURN(chunk);
! 147: }
! 148: /* }}} */
! 149:
! 150:
! 151: /* {{{ mysqlnd_mempool_create */
! 152: PHPAPI MYSQLND_MEMORY_POOL *
! 153: mysqlnd_mempool_create(size_t arena_size TSRMLS_DC)
! 154: {
! 155: /* We calloc, because we free(). We don't mnd_calloc() for a reason. */
! 156: MYSQLND_MEMORY_POOL * ret = mnd_calloc(1, sizeof(MYSQLND_MEMORY_POOL));
! 157: DBG_ENTER("mysqlnd_mempool_create");
! 158: if (ret) {
! 159: ret->get_chunk = mysqlnd_mempool_get_chunk;
! 160: ret->free_size = ret->arena_size = arena_size ? arena_size : 0;
! 161: ret->refcount = 0;
! 162: /* OOM ? */
! 163: ret->arena = mnd_malloc(ret->arena_size);
! 164: if (!ret->arena) {
! 165: mysqlnd_mempool_destroy(ret TSRMLS_CC);
! 166: ret = NULL;
! 167: }
! 168: }
! 169: DBG_RETURN(ret);
! 170: }
! 171: /* }}} */
! 172:
! 173:
! 174: /* {{{ mysqlnd_mempool_destroy */
! 175: PHPAPI void
! 176: mysqlnd_mempool_destroy(MYSQLND_MEMORY_POOL * pool TSRMLS_DC)
! 177: {
! 178: DBG_ENTER("mysqlnd_mempool_destroy");
! 179: /* mnd_free will reference LOCK_access and might crash, depending on the caller...*/
! 180: mnd_free(pool->arena);
! 181: mnd_free(pool);
! 182: DBG_VOID_RETURN;
! 183: }
! 184: /* }}} */
! 185:
! 186:
! 187: /*
! 188: * Local variables:
! 189: * tab-width: 4
! 190: * c-basic-offset: 4
! 191: * End:
! 192: * vim600: noet sw=4 ts=4 fdm=marker
! 193: * vim<600: noet sw=4 ts=4
! 194: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>