/* ** Merge as possible the next block or/and ** the previous block with the current parameter. ** Return the new address of the current block. */ t_ptr heap_merge(t_ptr block) { size_t size; size_t prev_state; size_t next_state; assert(!IS_B_ALLOC(block)); size = GET_B_SIZE(block); prev_state = IS_B_ALLOC(GET_PREV(block)); next_state = IS_B_ALLOC(GET_NEXT(block)); if (!prev_state) { size += GET_B_SIZE(GET_PREV(block)); if (!next_state) size += GET_B_SIZE(GET_NEXT(block)); SET(GET_HEAD(GET_PREV(block)), PACK(size, 0)); SET(GET_FOOT(GET_PREV(block)), PACK(size, 0)); block = GET_PREV(block); } else if (!next_state) { size += GET_B_SIZE(GET_NEXT(block)); SET(GET_HEAD(block), PACK(size, 0)); SET(GET_FOOT(block), PACK(size, 0)); } return (block); }
/* ** Extend the heap by words_nbr * WORD_SIZE bytes. ** If words_nbr is not a multiple of 2, one word is added. */ t_ptr heap_extend(size_t words_nbr) { size_t size; t_ptr new_block; size = (words_nbr % 2 ? words_nbr + 1: words_nbr) * WORD_SIZE; if ((new_block = sbrk(size)) == NULL) return (NULL); SET(GET_HEAD(new_block), PACK(size, 0)); SET(GET_FOOT(new_block), PACK(size, 0)); SET(GET_HEAD(GET_NEXT(new_block)), PACK(0, 1)); return (heap_merge(new_block)); }
VOID arrange_tree(LONG tree, WORD wint, WORD hint,WORD *maxw, WORD *maxh) { WORD obj, x, y, rowh, wroot; wroot = GET_WIDTH(tree, ROOT); if ( wroot ) { x = wint; y = hint; rowh = 0; *maxw = 0; for (obj = GET_HEAD(tree, ROOT); obj != ROOT; obj = GET_NEXT(tree, obj)) { if (rowh && (x + GET_WIDTH(tree, obj)) > wroot) { x = wint; y += (rowh + hint); rowh = 0; } SET_X(tree, obj, x); SET_Y(tree, obj, y); if ( !(GET_FLAGS(tree, obj) & HIDETREE) ) { x += (GET_WIDTH(tree, obj) + wint); *maxw = max(*maxw, x); rowh = max(rowh, GET_HEIGHT(tree, obj)); } } *maxh = y + rowh + hint; } }
WORD child_of(LONG tree, WORD nobj, WORD obj) { WORD nbar; nobj = GET_HEAD(tree, nobj); for (nbar = 1; nobj != obj; nbar++) nobj = GET_NEXT(tree, nobj); return (nbar); }
/* ** Reserve size bytes in the current block. ** Split the current block if it is possible. */ void heap_reserve(t_ptr block, size_t size) { size_t block_size; assert(!IS_B_ALLOC(block)); block_size = GET_B_SIZE(block); assert(block_size >= size); if (block_size - size >= DWORD_SIZE + EXTRA_SIZE) { SET(GET_HEAD(block), PACK(size, 1)); SET(GET_FOOT(block), PACK(size, 1)); SET(GET_HEAD(GET_NEXT(block)), PACK(block_size - size, 0)); SET(GET_FOOT(GET_NEXT(block)), PACK(block_size - size, 0)); } else { SET(GET_HEAD(block), PACK(block_size, 1)); SET(GET_FOOT(block), PACK(block_size, 1)); } }
/* ** Free ... ** - set the "reserved" boolean at 0 ** - defrag from the current block */ void free(void *ptr) { t_ptr block; size_t size; if (ptr) { block = (t_ptr)ptr; assert(IS_B_ALLOC(block)); size = GET_B_SIZE(block); SET(GET_HEAD(block), PACK(size, 0)); SET(GET_FOOT(block), PACK(size, 0)); heap_merge(block); } }
/* ** Realloc by merging the next if it isn't reserved. ** Return 0 if the realloc has been done, -1 otherwise */ static int realloc_by_merge(t_ptr block, size_t size) { size_t total_size; size_t real_size; if (size <= DWORD_SIZE) real_size = size + EXTRA_SIZE; else { real_size = ((size + EXTRA_SIZE + DWORD_SIZE - 1) / DWORD_SIZE) * DWORD_SIZE; } total_size = GET_B_SIZE(block) + GET_B_SIZE(GET_NEXT(block)); if (IS_B_ALLOC(GET_NEXT(block)) || total_size < real_size) return (-1); SET(GET_HEAD(block), PACK(total_size, 0)); SET(GET_FOOT(block), PACK(total_size, 0)); heap_reserve(block, real_size); return (0); }
void Ps_Free(void *p) { struct mm_head *head = GET_HEAD(p); int size = head->size; assert(size > 0); if(size > SMALL_MEM_LIMIT) { free((void*)head); } else { assert(size / BLOCK_BASE * BLOCK_BASE == size); MM_GET_LOCK(); *(long*)head = (long)mm_structs[SIZE2INDEX(size)].frees; mm_structs[SIZE2INDEX(size)].frees = head; MM_RELEASE_LOCK(); } }
WORD nth_child(LONG tree, WORD nobj, WORD n) { for (nobj = GET_HEAD(tree, nobj); --n; nobj = GET_NEXT(tree, nobj)) ; return (nobj); }