Changeset 1135 for trunk/xcache/xc_allocator.c
- Timestamp:
- 2012-08-09T11:04:02+02:00 (10 months ago)
- Location:
- trunk
- Files:
-
- 1 edited
- 1 moved
-
. (modified) (1 prop)
-
xcache/xc_allocator.c (moved) (moved from trunk/xcache/xc_mem.c) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:ignore
-
trunk/xcache/xc_allocator.c
r1127 r1135 1 #ifdef TEST 2 # include <limits.h> 3 # include <stdio.h> 4 # define XCACHE_DEBUG 5 typedef int zend_bool; 6 # define ZEND_ATTRIBUTE_PTR_FORMAT(a, b, c) 7 # define zend_error(type, error) fprintf(stderr, "%s", error) 8 #else 9 # include <php.h> 1 #include "xc_allocator.h" 2 #include <string.h> 3 #include <stdio.h> 4 5 typedef struct { 6 const char *name; 7 const xc_allocator_vtable_t *allocator_vtable; 8 } xc_allocator_info_t; 9 static xc_allocator_info_t xc_allocator_infos[10]; 10 11 int xc_allocator_register(const char *name, const xc_allocator_vtable_t *allocator_vtable) /* {{{ */ 12 { 13 size_t i; 14 for (i = 0; i < sizeof(xc_allocator_infos) / sizeof(xc_allocator_infos[0]); i ++) { 15 if (!xc_allocator_infos[i].name) { 16 xc_allocator_infos[i].name = name; 17 xc_allocator_infos[i].allocator_vtable = allocator_vtable; 18 return 1; 19 } 20 } 21 return 0; 22 } 23 /* }}} */ 24 const xc_allocator_vtable_t *xc_allocator_find(const char *name) /* {{{ */ 25 { 26 size_t i; 27 for (i = 0; i < sizeof(xc_allocator_infos) / sizeof(xc_allocator_infos[0]) && xc_allocator_infos[i].name; i ++) { 28 if (strcmp(xc_allocator_infos[i].name, name) == 0) { 29 return xc_allocator_infos[i].allocator_vtable; 30 } 31 } 32 return NULL; 33 } 34 /* }}} */ 35 void xc_allocator_init() /* {{{ */ 36 { 37 extern void xc_allocator_bestfit_register(); 38 #ifdef HAVE_XCACHE_TEST 39 extern void xc_allocator_malloc_register(); 10 40 #endif 11 41 12 #ifdef XCACHE_DEBUG 13 # define ALLOC_DEBUG_BLOCK_CHECK 42 memset(xc_allocator_infos, 0, sizeof(xc_allocator_infos)); 43 xc_allocator_bestfit_register(); 44 #ifdef HAVE_XCACHE_TEST 45 xc_allocator_malloc_register(); 14 46 #endif 15 16 17 #include <assert.h>18 #include <stdlib.h>19 #include <string.h>20 #define XC_MEMBLOCK_IMPL _xc_mem_block_t21 #define XC_MEM_IMPL _xc_mem_mem_t22 #include "xc_shm.h"23 #include "util/xc_align.h"24 #include "util/xc_trace.h"25 26 #if 027 #undef ALLOC_DEBUG_BLOCK_CHECK28 #endif29 30 #define CHAR_PTR(p) ((char *) (p))31 #define PADD(p, a) (CHAR_PTR(p) + a)32 #define PSUB(p1, p2) (CHAR_PTR(p1) - CHAR_PTR(p2))33 34 /* {{{ mem */35 struct _xc_mem_block_t {36 #ifdef ALLOC_DEBUG_BLOCK_CHECK37 unsigned int magic;38 #endif39 xc_memsize_t size; /* reserved even after alloc */40 xc_block_t *next; /* not used after alloc */41 };42 43 struct _xc_mem_mem_t {44 const xc_mem_handlers_t *handlers;45 xc_shm_t *shm;46 xc_memsize_t size;47 xc_memsize_t avail; /* total free */48 xc_block_t headblock[1]; /* just as a pointer to first block*/49 };50 51 #ifndef XtOffsetOf52 # include <linux/stddef.h>53 # define XtOffsetOf(s_type, field) offsetof(s_type, field)54 #endif55 56 #define SizeOf(type, field) sizeof( ((type *) 0)->field )57 #define BLOCK_HEADER_SIZE() (ALIGN( XtOffsetOf(xc_block_t, size) + SizeOf(xc_block_t, size) ))58 59 #define BLOCK_MAGIC ((unsigned int) 0x87655678)60 61 /* }}} */62 static inline void xc_block_setup(xc_block_t *b, xc_memsize_t size, xc_block_t *next) /* {{{ */63 {64 #ifdef ALLOC_DEBUG_BLOCK_CHECK65 b->magic = BLOCK_MAGIC;66 #endif67 b->size = size;68 b->next = next;69 47 } 70 48 /* }}} */ 71 #ifdef ALLOC_DEBUG_BLOCK_CHECK72 static void xc_block_check(xc_block_t *b) /* {{{ */73 {74 if (b->magic != BLOCK_MAGIC) {75 fprintf(stderr, "0x%X != 0x%X magic wrong \n", b->magic, BLOCK_MAGIC);76 }77 }78 /* }}} */79 #else80 # define xc_block_check(b) do { } while(0)81 #endif82 83 84 static XC_MEM_MALLOC(xc_mem_malloc) /* {{{ */85 {86 xc_block_t *prev, *cur;87 xc_block_t *newb, *b;88 xc_memsize_t realsize;89 xc_memsize_t minsize;90 void *p;91 /* [xc_block_t:size|size] */92 realsize = BLOCK_HEADER_SIZE() + size;93 /* realsize is ALIGNed so next block start at ALIGNed address */94 realsize = ALIGN(realsize);95 96 TRACE("avail: %lu (%luKB). Allocate size: %lu realsize: %lu (%luKB)"97 , mem->avail, mem->avail / 102498 , size99 , realsize, realsize / 1024100 );101 do {102 p = NULL;103 if (mem->avail < realsize) {104 TRACE("%s", " oom");105 break;106 }107 108 b = NULL;109 minsize = ULONG_MAX;110 111 /* prev|cur */112 113 for (prev = mem->headblock; prev->next; prev = cur) {114 /* while (prev->next != 0) { */115 cur = prev->next;116 xc_block_check(cur);117 if (cur->size == realsize) {118 /* found a perfect fit, stop searching */119 b = prev;120 break;121 }122 /* make sure we can split on the block */123 else if (cur->size > (sizeof(xc_block_t) + realsize) &&124 cur->size < minsize) {125 /* cur is acceptable and memller */126 b = prev;127 minsize = cur->size;128 }129 prev = cur;130 }131 132 if (b == NULL) {133 TRACE("%s", " no fit chunk");134 break;135 }136 137 prev = b;138 139 cur = prev->next;140 p = PADD(cur, BLOCK_HEADER_SIZE());141 142 /* update the block header */143 mem->avail -= realsize;144 145 /* perfect fit, just unlink */146 if (cur->size == realsize) {147 prev->next = cur->next;148 TRACE(" perfect fit. Got: %p", p);149 break;150 }151 152 /* make new free block after alloced space */153 154 /* save, as it might be overwrited by newb (cur->size is ok) */155 b = cur->next;156 157 /* prev|cur |next=b */158 159 newb = (xc_block_t *)PADD(cur, realsize);160 xc_block_setup(newb, cur->size - realsize, b);161 cur->size = realsize;162 /* prev|cur|newb|next163 * `--^164 */165 166 TRACE(" -> avail: %lu (%luKB). new next: %p offset: %lu %luKB. Got: %p"167 , mem->avail, mem->avail / 1024168 , newb169 , PSUB(newb, mem), PSUB(newb, mem) / 1024170 , p171 );172 prev->next = newb;173 /* prev|cur|newb|next174 * `-----^175 */176 177 } while (0);178 179 return p;180 }181 /* }}} */182 static XC_MEM_FREE(xc_mem_free) /* {{{ return block size freed */183 {184 xc_block_t *cur, *b;185 int size;186 187 cur = (xc_block_t *) (CHAR_PTR(p) - BLOCK_HEADER_SIZE());188 TRACE("freeing: %p, size=%lu", p, cur->size);189 xc_block_check(cur);190 assert((char*)mem < (char*)cur && (char*)cur < (char*)mem + mem->size);191 192 /* find free block right before the p */193 b = mem->headblock;194 while (b->next != 0 && b->next < cur) {195 b = b->next;196 }197 198 /* restore block */199 cur->next = b->next;200 b->next = cur;201 size = cur->size;202 203 TRACE(" avail %lu (%luKB)", mem->avail, mem->avail / 1024);204 mem->avail += size;205 206 /* combine prev|cur */207 if (PADD(b, b->size) == (char *)cur) {208 b->size += cur->size;209 b->next = cur->next;210 cur = b;211 TRACE("%s", " combine prev");212 }213 214 /* combine cur|next */215 b = cur->next;216 if (PADD(cur, cur->size) == (char *)b) {217 cur->size += b->size;218 cur->next = b->next;219 TRACE("%s", " combine next");220 }221 TRACE(" -> avail %lu (%luKB)", mem->avail, mem->avail / 1024);222 return size;223 }224 /* }}} */225 static XC_MEM_CALLOC(xc_mem_calloc) /* {{{ */226 {227 xc_memsize_t realsize = memb * size;228 void *p = xc_mem_malloc(mem, realsize);229 230 if (p) {231 memset(p, 0, realsize);232 }233 return p;234 }235 /* }}} */236 static XC_MEM_REALLOC(xc_mem_realloc) /* {{{ */237 {238 void *newp = xc_mem_malloc(mem, size);239 if (p && newp) {240 memcpy(newp, p, size);241 xc_mem_free(mem, p);242 }243 return newp;244 }245 /* }}} */246 static XC_MEM_STRNDUP(xc_mem_strndup) /* {{{ */247 {248 void *p = xc_mem_malloc(mem, len + 1);249 if (p) {250 memcpy(p, str, len + 1);251 }252 return p;253 }254 /* }}} */255 static XC_MEM_STRDUP(xc_mem_strdup) /* {{{ */256 {257 return xc_mem_strndup(mem, str, strlen(str));258 }259 /* }}} */260 261 static XC_MEM_AVAIL(xc_mem_avail) /* {{{ */262 {263 return mem->avail;264 }265 /* }}} */266 static XC_MEM_SIZE(xc_mem_size) /* {{{ */267 {268 return mem->size;269 }270 /* }}} */271 272 static XC_MEM_FREEBLOCK_FIRST(xc_mem_freeblock_first) /* {{{ */273 {274 return mem->headblock->next;275 }276 /* }}} */277 XC_MEM_FREEBLOCK_NEXT(xc_mem_freeblock_next) /* {{{ */278 {279 return block->next;280 }281 /* }}} */282 XC_MEM_BLOCK_SIZE(xc_mem_block_size) /* {{{ */283 {284 return block->size;285 }286 /* }}} */287 XC_MEM_BLOCK_OFFSET(xc_mem_block_offset) /* {{{ */288 {289 return ((char *) block) - ((char *) mem);290 }291 /* }}} */292 293 static XC_MEM_INIT(xc_mem_init) /* {{{ */294 {295 xc_block_t *b;296 #define MINSIZE (ALIGN(sizeof(xc_mem_t)) + sizeof(xc_block_t))297 /* requires at least the header and 1 tail block */298 if (size < MINSIZE) {299 fprintf(stderr, "xc_mem_init requires %lu bytes at least\n", (unsigned long) MINSIZE);300 return NULL;301 }302 TRACE("size=%lu", size);303 mem->shm = shm;304 mem->size = size;305 mem->avail = size - MINSIZE;306 307 /* pointer to first block, right after ALIGNed header */308 b = mem->headblock;309 xc_block_setup(b, 0, (xc_block_t *) PADD(mem, ALIGN(sizeof(xc_mem_t))));310 311 /* first block*/312 b = b->next;313 xc_block_setup(b, mem->avail, 0);314 #undef MINSIZE315 316 return mem;317 }318 /* }}} */319 static XC_MEM_DESTROY(xc_mem_destroy) /* {{{ */320 {321 }322 /* }}} */323 324 49 #ifdef TEST 325 50 /* {{{ testing */ … … 333 58 #include <time.h> 334 59 335 int main()60 int testAllocator(const xc_allocator_vtable_t *allocator_vtable) 336 61 { 337 62 int count = 0; 338 63 void *p; 64 xc_allocator_t *allocator; 339 65 void *memory; 340 xc_mem_t *mem;341 66 void **ptrs; 342 67 int size, i; … … 350 75 CHECK(memory = malloc(size), "OOM"); 351 76 CHECK(ptrs = malloc(size * sizeof(void *)), "OOM"); 352 mem = (xc_mem_t *) memory; 353 CHECK(mem = xc_mem_init(NULL, mem, size), "Failed init memory allocator"); 77 allocator = (xc_allocator_t *) memory; 78 allocator->vtable = allocator_vtable; 79 CHECK(allocator = allocator->vtable->init(NULL, allocator, size), "Failed init memory allocator"); 354 80 355 while ((p = xc_mem_malloc(mem, 1))) {81 while ((p = allocator->vtable->malloc(allocator, 1))) { 356 82 ptrs[count ++] = p; 357 83 } … … 361 87 i = (random() % count); 362 88 fprintf(stderr, "freeing %d: ", i); 363 xc_mem_free(mem, ptrs[i]);89 allocator->vtable->free(allocator, ptrs[i]); 364 90 ptrs[i] = ptrs[count - 1]; 365 91 count --; … … 371 97 } 372 98 /* }}} */ 373 #endif 374 375 typedef struct { 376 const char *name; 377 const xc_mem_handlers_t *handlers; 378 } xc_mem_scheme_t; 379 static xc_mem_scheme_t xc_mem_schemes[10]; 380 381 int xc_mem_scheme_register(const char *name, const xc_mem_handlers_t *handlers) /* {{{ */ 99 int main() /* {{{ */ 382 100 { 383 101 int i; 384 for (i = 0; i < 10; i ++) { 385 if (!xc_mem_schemes[i].name) {386 xc_mem_schemes[i].name = name; 387 xc_mem_schemes[i].handlers = handlers;388 return 1;389 }102 103 xc_allocator_init(); 104 105 for (i = 0; i < sizeof(xc_allocator_infos) / sizeof(xc_allocator_infos[0]) && xc_allocator_infos[i].name; i ++) { 106 fprintf(stderr, "testing %s...\n", xc_allocator_infos[i].name); 107 testAllocator(xc_allocator_infos[i].allocator_vtable); 390 108 } 391 109 return 0; 392 110 } 393 111 /* }}} */ 394 const xc_mem_handlers_t *xc_mem_scheme_find(const char *name) /* {{{ */ 395 { 396 int i; 397 for (i = 0; i < 10 && xc_mem_schemes[i].name; i ++) { 398 if (strcmp(xc_mem_schemes[i].name, name) == 0) { 399 return xc_mem_schemes[i].handlers; 400 } 401 } 402 return NULL; 403 } 404 /* }}} */ 405 406 static xc_mem_handlers_t xc_mem_mem_handlers = XC_MEM_HANDLERS(mem); 407 void xc_shm_mem_init() /* {{{ */ 408 { 409 memset(xc_mem_schemes, 0, sizeof(xc_mem_schemes)); 410 411 if (xc_mem_scheme_register("mem", &xc_mem_mem_handlers) == 0) { 412 zend_error(E_ERROR, "XCache: failed to register mem mem_scheme"); 413 } 414 } 415 /* }}} */ 112 #endif
Note: See TracChangeset
for help on using the changeset viewer.

