Return to mysqlnd_block_alloc.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / mysqlnd |
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: */