![]() ![]() | ![]() |
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 2006-2013 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 21: /* $Id$ */
1.1 misho 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: */