byte *block_alloc(byte type, size_t size) { int s, b, found = 0, blocks = BLOCKS(size); byte *block_map; byte *space; if (arena_state != INITIALIZED) arena_init(); if (blocks > BLOCKS_PER_SPACE) error("Trying to allocate too many contiguous blocks."); for(s=0; s<SPACES_IN_ARENA; ++s) { if (space_type[s] == TYPE_BLOCKS) { block_map = SPACE_MAP(s); for (b=0; b<BLOCKS_PER_SPACE; b++) { if (block_map[b] == TYPE_FREE) { found ++; if(found >= blocks) { int start = b+1-found, k; for(k=start; k<=b; ++k) block_map[k] = type; map(BLOCK_BASE(s,start), GRAINROUND(page_size, size)); return(BLOCK_BASE(s,start)); } } else found = 0; } found = 0; } } /* None of the existing block spaces have room; let's make a new one */ space = space_alloc(TYPE_BLOCKS,0); /* allocate the new space */ s = SPACE(space); block_map = SPACE_MAP(s) = block_maps + s*BLOCKS_PER_SPACE; /* This is where the map is */ for(b=0; b< blocks; ++b) block_map[b] = type; for (b=blocks; b < BLOCKS_PER_SPACE; b++) block_map[b] = TYPE_FREE; /* ... and initialize it */ map(space, GRAINROUND(page_size, size)); return(space); }
static void set_alloc_ptr(struct alloc_ptr *ptr, struct segment *seg) { if (seg) { ptr->free = BLOCK_BASE(seg); BITPTR_INIT(ptr->freebit, BITMAP0_BASE(seg), 0); } else { ptr->free = NULL; ptr->freebit = dummy_bitptr; } }
static NOINLINE void * find_bitmap(struct alloc_ptr *ptr) { unsigned int i, index, *base, *limit, *p; struct segment *seg; bitptr_t b = ptr->freebit; void *obj; ASSERT(ptr->freebit.ptr != &dummy_bitmap); seg = ALLOC_PTR_TO_SEGMENT(ptr); BITPTR_NEXT(b); base = BITMAP0_BASE(seg); if (BITPTR_NEXT_FAILED(b)) { for (i = 1;; i++) { if (i >= SEG_RANK) { p = &BITPTR_WORD(b) + 1; limit = BITMAP_LIMIT(seg, SEG_RANK - 1); b = bitptr_linear_search(p, limit); if (BITPTR_NEXT_FAILED(b)) return NULL; i = SEG_RANK - 1; break; } index = BITPTR_WORDINDEX(b, base) + 1; base = BITMAP_BASE(seg, i); BITPTR_INIT(b, base, index); BITPTR_NEXT(b); if (!BITPTR_NEXT_FAILED(b)) break; } do { index = BITPTR_INDEX(b, base); base = BITMAP_BASE(seg, --i); BITPTR_INIT(b, base + index, 0); BITPTR_NEXT(b); ASSERT(!BITPTR_NEXT_FAILED(b)); } while (i > 0); } index = BITPTR_INDEX(b, base); obj = BLOCK_BASE(seg) + (index << seg->blocksize_log2); ASSERT(OBJ_TO_SEGMENT(obj) == seg); GCSTAT_ALLOC_COUNT(find, seg->blocksize_log2, ptr->blocksize_bytes); BITPTR_INC(b); ptr->freebit = b; ptr->free = (char*)obj + ptr->blocksize_bytes; return obj; }
void test_mapping(void) { int i,j; byte *block_map; for (i=0 ; i<NR_SPACES; ++i) { switch (space_type[i]) { case TYPE_RESERVED: /* these are reserved */ message("space at 0x%08x reserved",SPACE_BASE(i)); break; case TYPE_BLOCKS: /* test each block */ block_map = SPACE_MAP(i); message("testing block space at 0x%08x",SPACE_BASE(i)); for (j=0; j < BLOCKS_PER_SPACE; j++) { switch (block_map[j]) { case TYPE_FREE: message(" testing block at 0x%08x",BLOCK_BASE(i,j)); map (BLOCK_BASE(i,j), BLOCK_SIZE); unmap (BLOCK_BASE(i,j), BLOCK_SIZE); break; default: message(" block at 0x%08x has type %d", BLOCK_BASE(i,j),block_map[j]); } } break; case TYPE_FREE: /* test the whole space */ message("testing space at 0x%08x",SPACE_BASE(i)); map(SPACE_BASE(i), SPACE_SIZE >> 1); unmap(SPACE_BASE(i), SPACE_SIZE >> 1); break; default: message("space at 0x%08x used with type %d", SPACE_BASE(i), space_type[i]); } } }
/* for debug or GCSTAT */ static size_t segment_filled(struct segment *seg, size_t filled_index, size_t *ret_bytes) { unsigned int i; bitptr_t b; char *p = BLOCK_BASE(seg); size_t filled = 0, count = 0; const size_t blocksize = BLOCK_SIZE(seg); BITPTR_INIT(b, BITMAP0_BASE(seg), 0); for (i = 0; i < seg->layout->num_blocks; i++) { if (i < filled_index || BITPTR_TEST(b)) { ASSERT(OBJ_TOTAL_SIZE(p) <= blocksize); count++; filled += OBJ_TOTAL_SIZE(p); } BITPTR_INC(b); p += blocksize; } if (ret_bytes) *ret_bytes = filled; return count; }