XPT_NewArena(uint32_t block_size, size_t alignment, const char* name) { XPTArena *arena = calloc(1, sizeof(XPTArena)); if (arena) { XPT_ASSERT(alignment); if (alignment > sizeof(double)) alignment = sizeof(double); arena->alignment = alignment; if (block_size < XPT_MIN_BLOCK_SIZE) block_size = XPT_MIN_BLOCK_SIZE; arena->block_size = ALIGN_RND(block_size, alignment); /* must have room for at least one item! */ XPT_ASSERT(arena->block_size >= ALIGN_RND(sizeof(BLK_HDR), alignment) + ALIGN_RND(1, alignment)); if (name) { arena->name = XPT_STRDUP(arena, name); #ifdef XPT_ARENA_LOGGING /* fudge the stats since we are using space in the arena */ arena->LOG_MallocCallCount = 0; arena->LOG_MallocTotalBytesRequested = 0; arena->LOG_MallocTotalBytesUsed = 0; #endif /* XPT_ARENA_LOGGING */ } } return arena; }
XPT_NewArena(size_t block_size8, size_t block_size1) { XPTArena *arena = static_cast<XPTArena*>(calloc(1, sizeof(XPTArena))); if (arena) { if (block_size8 < XPT_MIN_BLOCK_SIZE) block_size8 = XPT_MIN_BLOCK_SIZE; arena->subarena8.block_size = ALIGN_RND(block_size8, 8); if (block_size1 < XPT_MIN_BLOCK_SIZE) block_size1 = XPT_MIN_BLOCK_SIZE; arena->subarena1.block_size = block_size1; } return arena; }
XPT_ArenaMalloc(XPTArena *arena, size_t size) { uint8_t *cur; size_t bytes; if (!size) return NULL; if (!arena) { XPT_ASSERT(0); return NULL; } bytes = ALIGN_RND(size, arena->alignment); LOG_MALLOC(arena, size, bytes); if (bytes > arena->space) { BLK_HDR* new_block; size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment); size_t new_space = arena->block_size; while (bytes > new_space - block_header_size) new_space += arena->block_size; new_block = (BLK_HDR*) calloc(new_space/arena->alignment, arena->alignment); if (!new_block) { arena->next = NULL; arena->space = 0; return NULL; } LOG_REAL_MALLOC(arena, new_space); /* link block into the list of blocks for use when we destroy */ new_block->next = arena->first; arena->first = new_block; /* save other block header info */ new_block->size = new_space; /* set info for current block */ arena->next = ((uint8_t*)new_block) + block_header_size; arena->space = new_space - block_header_size; #ifdef DEBUG /* mark block for corruption check */ memset(arena->next, 0xcd, arena->space); #endif } #ifdef DEBUG { /* do corruption check */ size_t i; for (i = 0; i < bytes; ++i) { XPT_ASSERT(arena->next[i] == 0xcd); } /* we guarantee that the block will be filled with zeros */ memset(arena->next, 0, bytes); } #endif cur = arena->next; arena->next += bytes; arena->space -= bytes; return cur; }
XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment) { if (!size) return NULL; if (!arena) { XPT_ASSERT(0); return NULL; } XPTSubArena *subarena; if (alignment == 8) { subarena = &arena->subarena8; } else if (alignment == 1) { subarena = &arena->subarena1; } else { XPT_ASSERT(0); return NULL; } size_t bytes = ALIGN_RND(size, alignment); if (bytes > subarena->space) { BLK_HDR* new_block; size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), alignment); size_t new_space = subarena->block_size; while (bytes > new_space - block_header_size) new_space += subarena->block_size; new_block = static_cast<BLK_HDR*>(calloc(new_space / alignment, alignment)); if (!new_block) { subarena->next = NULL; subarena->space = 0; return NULL; } /* link block into the list of blocks for use when we destroy */ new_block->next = subarena->first; subarena->first = new_block; /* set info for current block */ subarena->next = reinterpret_cast<uint8_t*>(new_block) + block_header_size; subarena->space = new_space - block_header_size; #ifdef DEBUG /* mark block for corruption check */ memset(subarena->next, 0xcd, subarena->space); #endif } #ifdef DEBUG { /* do corruption check */ size_t i; for (i = 0; i < bytes; ++i) { XPT_ASSERT(subarena->next[i] == 0xcd); } /* we guarantee that the block will be filled with zeros */ memset(subarena->next, 0, bytes); } #endif uint8_t* p = subarena->next; subarena->next += bytes; subarena->space -= bytes; return p; }