/*
* struct array_cache
*
* Per cpu structures
* Purpose:
* - LIFO ordering, to hand out cache-warm objects from _alloc
* - reduce the number of linked list operations
* - reduce spinlock operations
*
* The limit is stored in the per-cpu structure to reduce the data cache
* footprint.
*
*/
/**
* 空闲对象的本地高速缓存描述符(注意:是描述符而不是本地高速缓存本身,本地高速缓存在描述符后面)
*/
struct array_cache {
/**
* 指向本地高速缓存中可使用对象的指针的个数。
* 它同时也作为高速缓存中第一个空槽的下标。
*/
unsigned int avail;
/**
* 本地高速缓存的大小,也就是本地高速缓存中指针的最大个数
*/
unsigned int limit;
/**
* 本地高速缓存重新填充或者腾空时使用的块大小
*/
unsigned int batchcount;
/**
* 如果最近被使用过,则置为1
*/
unsigned int touched;
};
/* bootstrap: The caches do not work without cpuarrays anymore,
* but the cpuarrays are allocated from the generic caches...
*/
#define BOOT_CPUCACHE_ENTRIES1
struct arraycache_init {
struct array_cache cache;
void * entries[BOOT_CPUCACHE_ENTRIES];
};
//inline
static uint32_t next_pow_of_2( uint32_t x )
{
if( is_pow_of_2(x) ){
return x;
}
x |= x>>1;
x |= x>>2;
x |= x>>4;
x |= x>>8;
x |= x>>16;
return x+1;
}
//static inline int _index_offset(int index, int level, int max_level)
//为运行效率计,用inline,为调试方便计,去除inline
static int _index_offset( int index, int level, int max_level )
{
unsigned int ret;
void buddy_free( struct buddy *self, int offset )
{
assert( offset < (1<< self->level));
int left = 0;
int length = 1 << self->level;
int index = 0;
for( ; ; ){
switch( self->tree[index] )
{
case NODE_USED:
assert(offset == left);
_combine(self, index);
return;
case NODE_UNUSED:
assert(0);
return;
default:
length /= 2;
if( offset < left+length ){
index = index * 2 + 1;
}else{
left += length;
index = index * 2 + 2;
}
break;
}
}
}
//计算buddy的大小
int buddy_size( struct buddy * self, int offset )
{
assert( offset < (1<< self->level) );
int left = 0;
int length = 1 << self->level;
int index = 0;
for( ; ; ){
switch( self->tree[index] )
{
case NODE_USED:
assert(offset == left);
return length;
//相当于break
case NODE_UNUSED:
assert(0);
return length;
default:
length /= 2;
if( offset < left+length ){
index = index * 2 + 1;
}else{
left += length;
index = index * 2 + 2;
}
break;
}
}
}
//具有递归调用
static void _dump(struct buddy * self, int index , int level)
{
switch( self->tree[index] )
{
case NODE_UNUSED: //节点未使用
printf("(%d:%d)", _index_offset(index, level, self->level) , 1 << (self->level - level));
break;
case NODE_USED: //节点已使用
printf("[%d:%d]", _index_offset(index, level, self->level) , 1 << (self->level - level));
break;
case NODE_FULL: //节点已满
printf("{");
_dump(self, index * 2 + 1 , level+1);
//左孩子
_dump(self, index * 2 + 2 , level+1);
//右孩子
printf("}");
break;
default: //节点裂开 分叉 生了一对双胞胎左右儿子
printf("(");
_dump(self, index * 2 + 1 , level+1);
//左孩子
_dump(self, index * 2 + 2 , level+1);
//右孩子
printf(")");
break;
}
}
* Send me an email : http://www.codingnow.com/2000/gmail.gif
* My Blog : http://blog.codingnow.com
* http://blog.codingnow.com/2011/12/buddy_memory_allocation.html (in Chinese)