static void add_single_pages(struct page *base) /* Effects: Adds pages at base to the single_pages list */ { // fprintf(stderr, "## add_single_pages: base=%p, base->pagecount=%d\n", // base, base->pagecount); assert(base->pagecount > 0); pageid n = base->pagecount; struct page *prev = base->prev_address, *basenext = base->next_address, *next; single_page_count += n; for (;;) { // split 'base' into single pages. ASSERT_FREE(base); VALGRIND_MAKE_WRITABLE(base, sizeof(struct page)); base->free = 0; /* Not free so that coalesce won't steal these back */ base->prev_address = prev; // enforce the invariant that 'pagecount' is always correct: make sure // we record that this page has size 1 base->pagecount = 1; prev = base; base->next = single_pages; single_pages = base; if (--n == 0) break; next = (struct page *)((char *)base + RPAGESIZE); base->next_address = next; base = next; } base->next_address = basenext; basenext->prev_address = base; }
void add_single_pages(struct page *base) /* Effects: Adds pages at base to the single_pages list */ { pageid n; struct page *next; unsigned long int index; if (base == NULL) return; n = base->pagecount; index = base->list_id; single_pages[index].page_count += n; for ( ; ; ) { ASSERT_FREE(base); base->free = 0; /* Not free so that coalesce * won't steal these back */ base->next = single_pages[index].pages; single_pages[index].pages = base; if (--n == 0) break; next = (struct page*)( (char*)base + RPAGESIZE ); base = next; } }
struct page *alloc_single_page(struct page *next) { struct page *p; if (single_pages) { assert(single_page_count > 0); } else { scavenge_single_pages(PAGE_GROUP_SIZE); } ASSERT_FREE(single_pages); p = single_pages; single_pages = p->next; p->next = next; single_page_count--; // fprintf(stderr, "## alloc_single_page: p=%p\n", p); assert(p->pagecount > 0); return p; }