/* * heap_create_alloc_class_buckets -- (internal) allocates all cache bucket * instances of the specified type */ static int heap_create_alloc_class_buckets(struct palloc_heap *heap, struct alloc_class *c) { struct heap_rt *h = heap->rt; int i; for (i = 0; i < (int)h->ncaches; ++i) { h->caches[i].buckets[c->id] = bucket_new( container_new_seglists(heap), c); if (h->caches[i].buckets[c->id] == NULL) goto error_cache_bucket_new; } return 0; error_cache_bucket_new: for (i -= 1; i >= 0; --i) { bucket_delete(h->caches[i].buckets[c->id]); } return -1; }
static void test_heap(void) { struct mock_pop *mpop = MMAP_ANON_ALIGNED(MOCK_POOL_SIZE, Ut_mmap_align); PMEMobjpool *pop = &mpop->p; memset(pop, 0, MOCK_POOL_SIZE); pop->heap_offset = (uint64_t)((uint64_t)&mpop->heap - (uint64_t)mpop); pop->p_ops.persist = obj_heap_persist; pop->p_ops.memset_persist = obj_heap_memset_persist; pop->p_ops.base = pop; pop->set = MALLOC(sizeof(*(pop->set))); pop->set->options = 0; pop->set->directory_based = 0; struct stats *s = stats_new(pop); UT_ASSERTne(s, NULL); void *heap_start = (char *)pop + pop->heap_offset; uint64_t heap_size = MOCK_POOL_SIZE - sizeof(PMEMobjpool); struct palloc_heap *heap = &pop->heap; struct pmem_ops *p_ops = &pop->p_ops; UT_ASSERT(heap_check(heap_start, heap_size) != 0); UT_ASSERT(heap_init(heap_start, heap_size, &pop->heap_size, p_ops) == 0); UT_ASSERT(heap_boot(heap, heap_start, heap_size, &pop->heap_size, pop, p_ops, s, pop->set) == 0); UT_ASSERT(heap_buckets_init(heap) == 0); UT_ASSERT(pop->heap.rt != NULL); test_alloc_class_bitmap_correctness(); test_container((struct block_container *)container_new_ravl(heap), heap); test_container((struct block_container *)container_new_seglists(heap), heap); struct alloc_class *c_small = heap_get_best_class(heap, 1); struct alloc_class *c_big = heap_get_best_class(heap, 2048); UT_ASSERT(c_small->unit_size < c_big->unit_size); /* new small buckets should be empty */ UT_ASSERT(c_big->type == CLASS_RUN); struct memory_block blocks[MAX_BLOCKS] = { {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0} }; struct bucket *b_def = heap_bucket_acquire_by_id(heap, DEFAULT_ALLOC_CLASS_ID); for (int i = 0; i < MAX_BLOCKS; ++i) { heap_get_bestfit_block(heap, b_def, &blocks[i]); UT_ASSERT(blocks[i].block_off == 0); } heap_bucket_release(heap, b_def); struct memory_block old_run = {0, 0, 1, 0}; struct memory_block new_run = {0, 0, 0, 0}; struct alloc_class *c_run = heap_get_best_class(heap, 1024); struct bucket *b_run = heap_bucket_acquire(heap, c_run); /* * Allocate blocks from a run until one run is exhausted. */ UT_ASSERTne(heap_get_bestfit_block(heap, b_run, &old_run), ENOMEM); int *nresv = bucket_current_resvp(b_run); do { new_run.chunk_id = 0; new_run.block_off = 0; new_run.size_idx = 1; UT_ASSERTne(heap_get_bestfit_block(heap, b_run, &new_run), ENOMEM); UT_ASSERTne(new_run.size_idx, 0); *nresv = 0; } while (old_run.block_off != new_run.block_off); *nresv = 0; heap_bucket_release(heap, b_run); stats_delete(pop, s); UT_ASSERT(heap_check(heap_start, heap_size) == 0); heap_cleanup(heap); UT_ASSERT(heap->rt == NULL); FREE(pop->set); MUNMAP_ANON_ALIGNED(mpop, MOCK_POOL_SIZE); }