static Uint BKT_MIN_SZ(GFAllctr_t *gfallctr, int ix) { Uint size; ASSERT(0 <= ix && ix <= BKT_MAX_IX_D); size = BKT_MIN_SZ_(gfallctr, ix); #ifdef ERTS_ALLOC_UTIL_HARD_DEBUG ASSERT(ix == BKT_IX(gfallctr, size)); ASSERT(size == MIN_BLK_SZ || ix - 1 == BKT_IX(gfallctr, size - 1)); #endif return size; }
UWord erts_gfalc_test(UWord op, UWord a1, UWord a2) { switch (op) { case 0x100: return (UWord) BKT_IX((GFAllctr_t *) a1, (Uint) a2); case 0x101: return (UWord) BKT_MIN_SZ((GFAllctr_t *) a1, (int) a2); case 0x102: return (UWord) NO_OF_BKTS; case 0x103: return (UWord) find_bucket(&((GFAllctr_t *) a1)->bucket_mask, (int) a2); default: ASSERT(0); return ~((UWord) 0); } }
unsigned long erts_gfalc_test(unsigned long op, unsigned long a1, unsigned long a2) { switch (op) { case 0x100: return (unsigned long) BKT_IX((GFAllctr_t *) a1, (Uint) a2); case 0x101: return (unsigned long) BKT_MIN_SZ((GFAllctr_t *) a1, (int) a2); case 0x102: return (unsigned long) NO_OF_BKTS; case 0x103: return (unsigned long) find_bucket(&((GFAllctr_t *) a1)->bucket_mask, (int) a2); default: ASSERT(0); return ~((unsigned long) 0); } }
static Block_t * get_free_block(Allctr_t *allctr, Uint size, Block_t *cand_blk, Uint cand_size) { GFAllctr_t *gfallctr = (GFAllctr_t *) allctr; int unsafe_bi, min_bi; Block_t *blk; ASSERT(!cand_blk || cand_size >= size); unsafe_bi = BKT_IX(gfallctr, size); min_bi = find_bucket(&gfallctr->bucket_mask, unsafe_bi); if (min_bi < 0) return NULL; if (min_bi == unsafe_bi) { blk = search_bucket(allctr, min_bi, size); if (blk) { if (cand_blk && cand_size <= MBC_FBLK_SZ(blk)) return NULL; /* cand_blk was better */ unlink_free_block(allctr, blk); return blk; } if (min_bi < NO_OF_BKTS - 1) { min_bi = find_bucket(&gfallctr->bucket_mask, min_bi + 1); if (min_bi < 0) return NULL; } else return NULL; } else { ASSERT(min_bi > unsafe_bi); } /* We are guaranteed to find a block that fits in this bucket */ blk = search_bucket(allctr, min_bi, size); ASSERT(blk); if (cand_blk && cand_size <= MBC_FBLK_SZ(blk)) return NULL; /* cand_blk was better */ unlink_free_block(allctr, blk); return blk; }
static void unlink_free_block(Allctr_t *allctr, Block_t *block) { GFAllctr_t *gfallctr = (GFAllctr_t *) allctr; GFFreeBlock_t *blk = (GFFreeBlock_t *) block; Uint sz = MBC_FBLK_SZ(&blk->block_head); int i = BKT_IX(gfallctr, sz); if (!blk->prev) { ASSERT(gfallctr->buckets[i] == blk); gfallctr->buckets[i] = blk->next; } else blk->prev->next = blk->next; if (blk->next) blk->next->prev = blk->prev; if (!gfallctr->buckets[i]) UNSET_BKT_MASK_IX(gfallctr->bucket_mask, i); }
static void link_free_block(Allctr_t *allctr, Block_t *block) { GFAllctr_t *gfallctr = (GFAllctr_t *) allctr; GFFreeBlock_t *blk = (GFFreeBlock_t *) block; Uint sz = MBC_FBLK_SZ(&blk->block_head); int i = BKT_IX(gfallctr, sz); ASSERT(sz >= MIN_BLK_SZ); SET_BKT_MASK_IX(gfallctr->bucket_mask, i); blk->prev = NULL; blk->next = gfallctr->buckets[i]; if (blk->next) { ASSERT(!blk->next->prev); blk->next->prev = blk; } gfallctr->buckets[i] = blk; }
void check_block(Allctr_t *allctr, Block_t * blk, int free_block) { GFAllctr_t *gfallctr = (GFAllctr_t *) allctr; int i; int bi; int found; GFFreeBlock_t *fblk; if(free_block) { Uint blk_sz = is_sbc_blk(blk) ? SBC_BLK_SZ(blk) : MBC_BLK_SZ(blk); bi = BKT_IX(gfallctr, blk_sz); ASSERT(gfallctr->bucket_mask.main & (((UWord) 1) << IX2SMIX(bi))); ASSERT(gfallctr->bucket_mask.sub[IX2SMIX(bi)] & (((UWord) 1) << IX2SBIX(bi))); found = 0; for (fblk = gfallctr->buckets[bi]; fblk; fblk = fblk->next) if (blk == (Block_t *) fblk) found++; ASSERT(found == 1); } else bi = -1; found = 0; for (i = 0; i < NO_OF_BKTS; i++) { if (i == bi) continue; /* Already checked */ for (fblk = gfallctr->buckets[i]; fblk; fblk = fblk->next) if (blk == (Block_t *) fblk) found++; } ASSERT(found == 0); }