#include"buddy.h"
#include"defs.h"
free_area_t free_area[MAX_ORDER];//定义free_area_t类型的free_area数组
struct Page*mem_map;
const int FreeAreaSize[MAX_ORDER]={1,2,4,8,16,32,64,128,256,512,1024};//定义数组FreeAreaSize
void test_buddy();
//check if pointer page indicates the first page frame of a block of order_size pages
//if so ,return1 ,else return 0;
int page_is_buddy(struct Page *page,int order)//页是在buddy系统中
{
if(PageProperty(page)&&page->property==order&&!PageReserved(page))
return 1;
return 0;
void init_memmap_buddy(struct Page*base,unsigned long nr)//对初始化内存把空闲内存放到buddy系统上
{
int i,order;
struct Page*page=base ;
mem_map=base;
for(i=0;i<MAX_ORDER;i++)
{
if(!LIST_EMPTY(&(free_area[i].free_list)))
panic("error");
}
while(nr)
{
for(order=10;order>=0;order--)//分配内存到buddy系统上
{
if(nr>=FreeAreaSize[i])
LIST_INSERT_HEAD(&(free_area[order].free_list),page,lru);
free_area[order].nr_free++;
page->property=order;
nr-=FreeAreaSize[order];
page+=FreeAreaSize[order];
break;
}
}
}
//在buddy系统上寻找合适的空闲块分配给请求的大小
struct Page*alloc_pages_buddy(int nr)
{
struct Page*p;
for(i=0;i<MAX_ORDER;i++){
if(nr<frea_area[i])
{
p=alloc_pages_buddy_bulk(i);
dbmsg("cpu%xkalloc%x":order%d;/n",cpu(),p-pages,i);
return p;
}
}
return NULL;
}
//implement buddy system strategy for freeing page frame;
struct Page*alloc_pages_bulk_buddy(int order)
{
int isalloc=0;
int current_order,size=0;
struct Page*page=NULL,*buddy=NULL;
for(current_order=order;current_order<MAX_ORDER;current_order++)
if(!LIST_EMPTY(&(free_area[current_order].free_list)))
{
isalloc=1;
break;
}
if(!isalloc)
return NULL;
//找到空闲物理块然后分配出去
else{
page=LIST_FIRST(&(free_area[current_order].free_list));
LIST_REMOVE(page,lru);
page->property=0;
ClearPageProperty(page);
free_area[current_order].nr_free--;
}
size=1<<current_order;
//从大到小进行折半操作
while(current_order>order)
{
current_order--;
size>>=1;
buddy=page+size;
LIST_INSERT_HEAD(&(free_area[current_order].free_list),buddy,lru)
buddy->property=current_order;
SetPageProperty(buddy);
free_area[current_order].nr_free++;
}
return page;
}
//按buddy系统的策略释放页框
//找到最贴近nr大小的FreeAreaSize[i],这时i是要和buddy系统上的伙伴合并的块的位置
void free_pages_buddy(struct Page*page,int nr)
{int i;
for(i=0;i<MAX_OEDER;i++)
if(nr<FreeAreaSize[i])
{
dbmsg("kfree %x : order %d/n", page - pages, i);
free_pages_bulk_buddy(page,i);
return;
}
}
}
//
void free_pages_bulk_buddy(struct Page*page,int order)
{
int size=1<<order;
unsigned long page_idx=page-mem_map,buddy_idx;
struct Page*buddy,*coalesced;
while(order<10)
{
buddy_idx=size^page_idx;//找mem_map数组上page_idx的buddy;
buddy=&mem_map[buddy_idx];//将buddy_idx为下标的数组的地址给buddy指针
if(!page_is_buddy(buddy,order))
break;
LIST_REMOVE(buddy,lru);//删除buddy上释放块的伙伴!
free_area[order].nr_free--;
buddy->property=0; //
ClearPageProperty(buddy);//
page_idx&=buddy_idx;
order++;
size>>1;
}
coalesced=&mem_map[page_idx];
dbmsg("free order %x,page %x/n",order,coalesced-pages);
coalesced->property=order;
SetPageProperty(coalesced);
LIST_INSERT_HEAD(&(free_area[order].free_list),coalesced,lru);
free_area[order].nr_free++;