struct page *alloc_pages(struct buddy *pool, unsigned int order) { struct buddy_freelist *freelist = &pool->free[order]; struct list *head, *curr; struct page *page; unsigned int i; for (i = order; i < BUDDY_MAX_ORDER; i++, freelist++) { head = &freelist->list; curr = head->next; if (curr != head) { page = get_container_of(curr, struct page, link); list_del(curr); BITMAP_TOGGLE(freelist->bitmap, PAGE_INDEX(page->addr), i); /* if allocating from higher order, split in half to add * one of them to current order. */ while (i > order) { freelist--; i--; list_add(&page->link, &freelist->list); BITMAP_TOGGLE(freelist->bitmap, PAGE_INDEX(page->addr), i); page += 1 << i; } pool->nr_free -= 1 << order; SET_PAGE_ORDER(page, order); SET_PAGE_FLAG(page, PAGE_BUDDY); return page; } }
void free_pages(struct buddy *pool, struct page *page) { struct page *buddy; struct buddy_freelist *freelist; unsigned int order, index; order = GET_PAGE_ORDER(page); freelist = &pool->free[order]; index = PAGE_INDEX(page->addr); pool->nr_free += 1U << order; while (order < BUDDY_MAX_ORDER) { BITMAP_TOGGLE(freelist->bitmap, index, order); /* If it was 0 before toggling, it means both of buddies * were allocated. So nothing can be merged to upper order * as one of them is still allocated. Otherwise, both of * them are free now. Therefore merge it to upper order. */ if (BITMAP_MASK(freelist->bitmap, index, order)) break; /* find buddy and detach it from current order to merge */ buddy = &mem_map[index ^ (1U << order)]; list_del(&buddy->link); /* grab the first address of merging buddies */ index &= ~(1U << order); order++; freelist++; } list_add(&mem_map[index].link, &freelist->list); RESET_PAGE_FLAG(page, PAGE_BUDDY); }
/* Write data to specified page */ RV NandDevice04::WritePage(BLOCK_ID blockID, PAGE_ID pageID, const BYTE * buffer, int offset, int size) { ASSERT(eraseCounter); ASSERT(blockID >= 0 && blockID < info.blockCount); ASSERT(pageID >= 0 && pageID < info.pageCountPerBlock); if (eraseCounter[blockID] >= info.eraseLimitation) { return RV_ERROR_FLASH_BLOCK_BROKEN; } // write process vfImage.seekg(blockID * blockSize + pageID * info.pageSize, ios::beg); vfImage.write((const char *)buffer, info.pageSize); vfImage.flush(); writeCounter[PAGE_INDEX(blockID, pageID)] ++; writeLatencyTotal += info.programTime; return RV_OK; }