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>