/* TBD: recover unusued portions of pages for use as individual pages */ #include "ti_config.h" #include "backend.h" #include "regions.h" #include void *alloc_block(Region r, struct allocator *a, struct ablock *blk, int n, size_t blksize) { struct page *newp; void *p; if (blk->allocfrom + n > blksize) { /* mark end of this page if not 100% full */ /* (usless but harmless on atomic pages) */ if (blk->allocfrom + sizeof(void *) <= blksize) *(void **)((char *)blk->base + blk->allocfrom) = NULL; if (blksize == RPAGESIZE) { newp = alloc_single_page(a->pages); a->pages = newp; } else { newp = alloc_pages(blksize >> RPAGELOG, a->bigpages); a->bigpages = newp; } blk->allocfrom = ALIGN(offsetof(struct page, previous), RALIGNMENT); set_region(newp, blksize >> RPAGELOG, r); blk->base = (char *)newp; } ASSERT_INUSE(blk->base, r); p = blk->base + blk->allocfrom; blk->allocfrom += n; return p; } void *qalloc(Region r, struct allocator *a, size_t n) { struct page *p; int npages; if (n <= RPAGESIZE / K) return alloc_block(r, a, &a->page, n, RPAGESIZE); if (n <= RPAGESIZE) return alloc_block(r, a, &a->superpage, n, K * RPAGESIZE); if (n <= RPAGESIZE * K) return alloc_block(r, a, &a->hyperpage, n, K * K * RPAGESIZE); npages = (n + offsetof(struct page, previous) + RPAGESIZE - 1) >> RPAGELOG; p = alloc_pages(npages, a->bigpages); a->bigpages = p; set_region(p, npages, r); return (char *)p + offsetof(struct page, previous); } void free_all_pages(Region r, struct allocator *a) /* Assumes PAGEALLOC lock held */ { struct page *p = a->pages; struct page *bigp = a->bigpages; struct page *next; for ( ; bigp ; bigp = next) { next = bigp->next; free_pages(r, bigp); } /* single pages are freed second, because they include the Region data structures (last one on the list) */ for ( ; p ; p = next) { next = p->next; free_single_page(r, p); } }