#include "includes.h" struct memarena { char *buf; size_t buf_used, buf_size; char **other_bufs; int n_other_bufs; }; MEMARENA memarena_create (void) { MEMARENA MALLOC(result); assert(result); result->buf_size = 1024; result->buf_used = 0; result->other_bufs = NULL; result->n_other_bufs = 0; result->buf = toku_malloc(result->buf_size); assert(result->buf); return result; } void memarena_clear (MEMARENA ma) { // Free the other bufs. int i; for (i=0; in_other_bufs; i++) { toku_free(ma->other_bufs[i]); ma->other_bufs[i]=0; } ma->n_other_bufs=0; // But reuse the main buffer ma->buf_used = 0; } static size_t round_to_page (size_t size) { const size_t PAGE_SIZE = 4096; const size_t result = PAGE_SIZE+((size-1)&~(PAGE_SIZE-1)); assert(0==(result&(PAGE_SIZE-1))); // make sure it's aligned assert(result>=size); // make sure it's not too small assert(sizebuf_size < ma->buf_used + size) { // The existing block isn't big enough. // Add the block to the vector of blocks. if (ma->buf) { int old_n = ma->n_other_bufs; REALLOC_N(old_n+1, ma->other_bufs); assert(ma->other_bufs); ma->other_bufs[old_n]=ma->buf; ma->n_other_bufs = old_n+1; } // Make a new one { size_t new_size = 2*ma->buf_size; if (new_sizebuf = toku_malloc(new_size); assert(ma->buf); ma->buf_used = 0; ma->buf_size = new_size; } } // allocate in the existing block. char *result=ma->buf+ma->buf_used; ma->buf_used+=size; return result; } void *memarena_memdup (MEMARENA ma, const void *v, size_t len) { void *r=malloc_in_memarena(ma, len); memcpy(r,v,len); return r; } void memarena_close(MEMARENA *map) { MEMARENA ma=*map; if (ma->buf) { toku_free(ma->buf); ma->buf=0; } int i; for (i=0; in_other_bufs; i++) { toku_free(ma->other_bufs[i]); } if (ma->other_bufs) toku_free(ma->other_bufs); ma->other_bufs=0; ma->n_other_bufs=0; toku_free(ma); *map = 0; } #if defined(_WIN32) #include #include #endif void memarena_move_buffers(MEMARENA dest, MEMARENA source) { int i; char **other_bufs = dest->other_bufs; static int move_counter = 0; move_counter++; REALLOC_N(dest->n_other_bufs + source->n_other_bufs + 1, other_bufs); #if defined(_WIN32) if (other_bufs == 0) { char **new_other_bufs; printf("_CrtCheckMemory:%d\n", _CrtCheckMemory()); printf("Z: move_counter:%d dest:%p %p %d source:%p %p %d errno:%d\n", move_counter, dest, dest->other_bufs, dest->n_other_bufs, source, source->other_bufs, source->n_other_bufs, errno); new_other_bufs = toku_malloc((dest->n_other_bufs + source->n_other_bufs + 1)*sizeof (char **)); printf("new_other_bufs=%p errno=%d\n", new_other_bufs, errno); } #endif assert(other_bufs); dest->other_bufs = other_bufs; for (i=0; in_other_bufs; i++) { dest->other_bufs[dest->n_other_bufs++] = source->other_bufs[i]; } dest->other_bufs[dest->n_other_bufs++] = source->buf; source->n_other_bufs = 0; toku_free(source->other_bufs); source->other_bufs = 0; source->buf = 0; source->buf_size = 0; source->buf_used = 0; }