void *alloc_newsb(procheap_t *fromheap) { desc_t *new_desc; struct anchor_struct anchor_st; struct active_struct active_st; active_t new_active; anchor_t new_anchor; void *ret; DPRINTF("alloc from new-sb\n"); /* desc address must be aligned to store credits in active */ //new_desc = (desc_t *)memalign(ACTIVE_ADDR_ALIGN, //sizeof(desc_t)); new_desc = get_desc(); /* allocate new super-block */ new_desc->sb = get_newsb(fromheap->sc->sbsize); setup_sb(new_desc->sb, fromheap->sc->sz, fromheap->sc->sbsize); /* setup descriptor */ new_desc->size = fromheap->sc->sz; new_desc->maxcount = fromheap->sc->sbsize / new_desc->size; new_desc->heap = fromheap; /* setup active for heap */ active_st.addr = new_desc; active_st.credits = MIN(new_desc->maxcount, MAXCREDITS) - 1; make_active(&active_st, &new_active); /* setup anchor for desc */ anchor_st.avail = 1; anchor_st.counter = new_desc->maxcount - active_st.credits - 1; anchor_st.state = ANCHOR_STATE_ACTIVE; /* set anchor into desc */ make_anchor(&(anchor_st), &new_anchor); memcpy((void *)&(new_desc->anchor), (void *)&new_anchor, sizeof(anchor_t)); /* * LOCATE MEMORY FENSE HERE * -> why? */ /* set active into heap -> must be done atomically */ if (atomic_cas((void *)&(fromheap->active), ZERO_ACTIVE, /* active is empty */ (u64)new_active) == ATOMIC_SUCCESS) { desc_t **p = (desc_t **)(new_desc->sb); DPRINTF("new superblock->%p\n", new_desc->sb); DPRINTF("new desc->%p\n", new_desc); DPRINTF("set new active:0x%llX\n", (u64)(new_active)); DPRINTF("set new anchor:0x%llX\n", (u64)(new_anchor)); *p = new_desc; ret = (void *)((desc_t **)new_desc->sb + 1); } else { /* another thread already have set new superblock, this thread do roll-back */ free(new_desc->sb); put_desc(new_desc); ret = NULL; } return ret; }
int main(int argc, char *argv[]) { #define BITMAP_BLOCKS 10 struct dev *dev = &(struct dev){ .bits = 3 }; /* This expect buffer is never reclaimed */ init_buffers(dev, 1 << 20, 1); block_t volblocks = BITMAP_BLOCKS << (dev->bits + 3); struct sb *sb = rapid_sb(dev); sb->super = INIT_DISKSB(dev->bits, volblocks); setup_sb(sb, &sb->super); test_init(argv[0]); struct inode *bitmap = rapid_open_inode(sb, NULL, 0); sb->bitmap = bitmap; /* Setup buffers for bitmap */ for (int block = 0; block < BITMAP_BLOCKS; block++) { struct buffer_head *buffer = blockget(bitmap->map, block); memset(bufdata(buffer), 0, sb->blocksize); set_buffer_clean(buffer); blockput(buffer); } /* Set fake backend mark to modify backend objects. */ tux3_start_backend(sb); if (test_start("test01")) test01(sb, BITMAP_BLOCKS); test_end(); if (test_start("test02")) test02(sb, BITMAP_BLOCKS); test_end(); if (test_start("test03")) test03(sb, BITMAP_BLOCKS); test_end(); if (test_start("test04")) test04(sb, BITMAP_BLOCKS); test_end(); if (test_start("test05")) test05(sb, BITMAP_BLOCKS); test_end(); if (test_start("test06")) test06(sb, BITMAP_BLOCKS); test_end(); if (test_start("test07")) test07(sb, BITMAP_BLOCKS); test_end(); if (test_start("test08")) test08(sb, BITMAP_BLOCKS); test_end(); tux3_end_backend(); clean_main(sb); return test_failures(); }