2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2008 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: Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
16 +----------------------------------------------------------------------+
18 This software was contributed to PHP by Yahoo! Inc. in 2008.
20 Future revisions and derivatives of this source code must acknowledge
21 Yahoo! Inc. as the original contributor of this module by
22 leaving this note intact in the source code.
24 All other licensing and usage conditions are those of the PHP Group.
28 /* $Id: apc_pool.c,v 3.3 2008/01/09 12:30:39 gopalv Exp $ */
34 #ifdef HAVE_VALGRIND_MEMCHECK_H
35 #include <valgrind/memcheck.h>
39 typedef struct _pool_block
44 struct _pool_block *next;
45 unsigned :0; /* this should align to word */
46 unsigned char data[0];
50 parts in ? are optional and turned on for fun, memory loss,
51 and for something else that I forgot about ... ah, debugging
53 |--------> data[0] |<-- non word boundary (too)
54 +-------------+--------------+-----------+-------------+-------------->>>
55 | pool_block | ?sizeinfo<1> | block<1> | ?redzone<1> | ?sizeinfo<2>
56 | | (size_t) | | padded left |
57 +-------------+--------------+-----------+-------------+-------------->>>
62 apc_malloc_t allocate;
63 apc_free_t deallocate;
70 unsigned int redzones:1;
71 unsigned int sizeinfo:1;
78 /* {{{ redzone code */
79 static const unsigned char decaff[] = {
80 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
81 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
82 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
83 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad
86 /* a redzone is at least 4 (0xde,0xca,0xc0,0xff) bytes */
87 #define REDZONE_SIZE(size) \
88 ((ALIGNWORD((size)) > ((size) + 4)) ? \
89 (ALIGNWORD((size)) - (size)) : /* does not change realsize */\
90 ALIGNWORD((size)) - (size) + ALIGNWORD((sizeof(char)))) /* adds 1 word to realsize */
92 #define SIZEINFO_SIZE ALIGNWORD(sizeof(size_t))
94 #define MARK_REDZONE(block, redsize) do {\
95 memcpy(block, decaff, redsize );\
98 #define CHECK_REDZONE(block, redsize) (memcmp(block, decaff, redsize) == 0)
102 #define APC_POOL_OPTION(pool, option) ((pool)->options.option)
104 /* {{{ create_pool_block */
105 static pool_block* create_pool_block(apc_pool *pool, size_t size)
107 size_t realsize = sizeof(pool_block) + ALIGNWORD(size);
109 pool_block* entry = pool->allocate(realsize);
111 entry->avail = entry->capacity = size;
113 entry->mark = entry->data;
115 entry->next = pool->head;
123 /* {{{ apc_pool_create */
124 apc_pool* apc_pool_create(apc_pool_type pool_type,
125 apc_malloc_t allocate,
126 apc_free_t deallocate)
128 apc_pool* pool = NULL;
132 assert(sizeof(decaff) > REDZONE_SIZE(ALIGNWORD(sizeof(char))));
133 assert(sizeof(pool_block) == ALIGNWORD(sizeof(pool_block)));
135 assert(APC_POOL_SIZE_MASK & (APC_POOL_SIZEINFO | APC_POOL_REDZONES) == 0);
137 switch(pool_type & APC_POOL_SIZE_MASK) {
146 case APC_MEDIUM_POOL:
154 pool = (apc_pool*)allocate(sizeof(apc_pool));
160 pool->allocate = allocate;
161 pool->deallocate = deallocate;
165 APC_POOL_OPTION(pool, redzones) = (pool_type & APC_POOL_REDZONES) != 0;
166 APC_POOL_OPTION(pool, sizeinfo) = (pool_type & APC_POOL_SIZEINFO) != 0;
168 if(!create_pool_block(pool, dsize)) {
177 /* {{{ apc_pool_destroy */
178 void apc_pool_destroy(apc_pool *pool)
181 apc_free_t deallocate = pool->deallocate;
187 while(entry != NULL) {
197 /* {{{ apc_pool_alloc */
198 void* apc_pool_alloc(apc_pool *pool, size_t size)
200 unsigned char *p = NULL;
201 size_t realsize = ALIGNWORD(size);
203 unsigned char *redzone = NULL;
205 size_t *sizeinfo= NULL;
210 if(APC_POOL_OPTION(pool, redzones)) {
211 redsize = REDZONE_SIZE(size); /* redsize might be re-using word size padding */
212 realsize = size + redsize; /* recalculating realsize */
214 redsize = realsize - size; /* use padding space */
217 if(APC_POOL_OPTION(pool, sizeinfo)) {
218 realsize += ALIGNWORD(sizeof(size_t));
222 for(entry = pool->head; entry != NULL; entry = entry->next) {
223 if(entry->avail >= realsize) {
228 poolsize = ALIGNSIZE(realsize, pool->dsize);
230 entry = create_pool_block(pool, poolsize);
239 if(APC_POOL_OPTION(pool, sizeinfo)) {
240 sizeinfo = (size_t*)p;
247 if(APC_POOL_OPTION(pool, redzones)) {
248 MARK_REDZONE(redzone, redsize);
251 #ifdef VALGRIND_MAKE_MEM_NOACCESS
253 VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
257 entry->avail -= realsize;
258 entry->mark += realsize;
260 #ifdef VALGRIND_MAKE_MEM_UNDEFINED
261 /* need to write before reading data off this */
262 VALGRIND_MAKE_MEM_UNDEFINED(p, size);
269 /* {{{ apc_pool_free */
271 * free does not do anything other than
272 * check for redzone values when free'ing
275 void apc_pool_free(apc_pool *pool, void *p)
277 if(!APC_POOL_OPTION(pool, sizeinfo) ||
278 !APC_POOL_OPTION(pool, redzones)) {
283 /* {{{ apc_pool_check_integrity */
285 * Checking integrity at runtime, does an
286 * overwrite check only when the sizeinfo
289 int apc_pool_check_integrity(apc_pool *pool)
292 size_t *sizeinfo = NULL;
293 unsigned char *start;
295 unsigned char *redzone;
298 for(entry = pool->head; entry != NULL; entry = entry->next) {
299 start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
300 if((entry->mark - start) != (entry->capacity - entry->avail)) {
305 if(!APC_POOL_OPTION(pool, sizeinfo) ||
306 !APC_POOL_OPTION(pool, redzones)) {
310 for(entry = pool->head; entry != NULL; entry = entry->next) {
311 start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
313 while(start < entry->mark) {
314 sizeinfo = (size_t*)start;
315 /* redzone starts where real data ends, in a non-word boundary
316 * redsize is at least 4 bytes + whatever's needed to make it
317 * to another word boundary.
319 redzone = start + SIZEINFO_SIZE + (*sizeinfo);
320 redsize = REDZONE_SIZE(*sizeinfo);
321 if(!CHECK_REDZONE(redzone, redsize))
324 fprintf(stderr, "Redzone check failed for %p\n",
325 start + ALIGNWORD(sizeof(size_t)));*/
328 realsize = SIZEINFO_SIZE + *sizeinfo + redsize;
342 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
343 * vim<600: expandtab sw=4 ts=4 sts=4