示例#1
0
文件: buddy.c 项目: onkwon/yaos
static inline bool is_buddy_free(struct page *page, struct page *buddy,
		unsigned int order)
{
	if ((GET_PAGE_FLAG(buddy) & PAGE_BUDDY) &&
			(order == GET_PAGE_ORDER(buddy)))
		return true;

	return false;
}
示例#2
0
文件: buddy.c 项目: onkwon/yaos
void free_pages(struct buddy *node, struct page *page)
{
	struct page *buddy, *mem_map;
	struct buddy_freelist *freelist;
	unsigned int order, idx, n;
	unsigned int irqflag;

	mem_map = node->mem_map;
	idx = page - mem_map;
	order = GET_PAGE_ORDER(page);
	freelist = &node->freelist[order];
	n = 1U << order;

	spin_lock_irqsave(&node->lock, irqflag);

	node->nr_free += n;

	while (order < (BUDDY_MAX_ORDER - 1)) {
		n = 1U << order;
		buddy = &mem_map[idx ^ n];

		if (!is_buddy_free(page, buddy, order))
			break;

		links_del(&buddy->list);
		freelist->nr_pageblocks--;
		RESET_PAGE_FLAG(buddy, PAGE_BUDDY);

		idx &= ~n; /* grab the head of merging buddies */
		order++;
		freelist++;
	}

	page = &mem_map[idx];
	links_add(&page->list, &freelist->list);
	freelist->nr_pageblocks++;
	SET_PAGE_FLAG(page, PAGE_BUDDY);
	SET_PAGE_ORDER(page, order);

	spin_unlock_irqrestore(&node->lock, irqflag);
}
示例#3
0
文件: buddy.c 项目: ccccjason/yaos
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);
}