root/ext/mysqlnd/mysqlnd_block_alloc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mysqlnd_mempool_free_chunk
  2. mysqlnd_mempool_resize_chunk
  3. mysqlnd_mempool_get_chunk
  4. mysqlnd_mempool_create
  5. mysqlnd_mempool_destroy

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 7                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 2006-2016 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$ */
  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)
  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_efree(chunk->ptr);
  48         }
  49         mnd_efree(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)
  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_emalloc(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_emalloc(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_erealloc(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)
 116 {
 117         MYSQLND_MEMORY_POOL_CHUNK *chunk = NULL;
 118         DBG_ENTER("mysqlnd_mempool_get_chunk");
 119 
 120         chunk = mnd_emalloc(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_emalloc(size);
 134                         if (!chunk->ptr) {
 135                                 chunk->free_chunk(chunk);
 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)
 154 {
 155         /* We calloc, because we free(). We don't mnd_calloc()  for a reason. */
 156         MYSQLND_MEMORY_POOL * ret = mnd_ecalloc(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_emalloc(ret->arena_size);
 164                 if (!ret->arena) {
 165                         mysqlnd_mempool_destroy(ret);
 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)
 177 {
 178         DBG_ENTER("mysqlnd_mempool_destroy");
 179         /* mnd_free will reference LOCK_access and might crash, depending on the caller...*/
 180         mnd_efree(pool->arena);
 181         mnd_efree(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  */

/* [<][>][^][v][top][bottom][index][help] */