一个程序明白buddy算法

#define method 2

#if  method == 0x00

#include<stdio.h>

#include<math.h>

/*

* 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_ENTRIES 1

struct arraycache_init {

struct array_cache cache;

void * entries[BOOT_CPUCACHE_ENTRIES];

};

static struct arraycache_init initarray_cache  =

{ { 0, BOOT_CPUCACHE_ENTRIES, 1, 0},{(void *) 0x11} };

static struct arraycache_init initarray_generic =

{ { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };

int main()

{

printf("sizeof(struct array_cache) = %d.\r\n", sizeof(struct array_cache) );

printf("sizeof(initarray_generic) = %d.\r\n", sizeof(initarray_generic) );

return 0;

}

#elif method == 0x01

#include <stdlib.h>

#include <assert.h>

#include <stdio.h>

#include <string.h>

static int fixsize( int size );

struct buddy2 {

unsigned size;

unsigned longest[1];

};

#define LEFT_LEAF(index) ((index) * 2 + 1)

#define RIGHT_LEAF(index) ((index) * 2 + 2)

#define PARENT(index) ( ((index) + 1) / 2 - 1)

#define IS_POWER_OF_2(x) (!((x)&((x)-1)))

#define MAX(a, b) ((a) > (b) ? (a) : (b))

#define ALLOC malloc

#define FREE free

//#define IS_POWER_OF_2(x)        ((x) != 0 && (((x) & ((x) - 1)) == 0))

struct buddy2* buddy2_new( int size ) {

struct buddy2* self;

unsigned node_size;

int i;

if (size < 1 || !IS_POWER_OF_2(size))

return NULL;

self = (struct buddy2*)ALLOC( 2 * size * sizeof(unsigned));

self->size = size;

node_size = size * 2;

for (i = 0; i < 2 * size - 1; ++i) {

if (IS_POWER_OF_2(i+1))

node_size /= 2;

self->longest[i] = node_size;

}

return self;

}

int buddy2_alloc(struct buddy2* self, int size) {

unsigned index = 0;

unsigned node_size;

unsigned offset = 0;

if (self==NULL)

return -1;

if (size <= 0)

size = 1;

else if (!IS_POWER_OF_2(size))

size = fixsize(size);

if (self->longest[index] < size)

return -1;

for(node_size = self->size; node_size != size; node_size /= 2 ) {

if (self->longest[LEFT_LEAF(index)] >= size)

index = LEFT_LEAF(index);

else

index = RIGHT_LEAF(index);

}

self->longest[index] = 0;

offset = (index + 1) * node_size - self->size;

while (index) {

index = PARENT(index);

self->longest[index] =

MAX(self->longest[LEFT_LEAF(index)], self->longest[RIGHT_LEAF(index)]);

}

return offset;

}

void buddy2_free(struct buddy2* self, int offset) {

unsigned node_size, index = 0;

unsigned left_longest, right_longest;

//assert(self && offset >= 0 && offset < size);

node_size = 1;

index = offset + self->size - 1;

for (; self->longest[index] ; index = PARENT(index)) {

node_size *= 2;

if (index == 0)

return;

}

self->longest[index] = node_size;

while (index) {

index = PARENT(index);

node_size *= 2;

left_longest = self->longest[LEFT_LEAF(index)];

right_longest = self->longest[RIGHT_LEAF(index)];

if (left_longest + right_longest == node_size)

self->longest[index] = node_size;

else

self->longest[index] = MAX(left_longest, right_longest);

}

}

#ifndef __BUDDY2_H__

#define __BUDDY2_H__

#include <stdlib.h>

struct buddy2;

struct buddy2* buddy2_new( int size );

void buddy2_destroy( struct buddy2* self );

int buddy2_alloc(struct buddy2* self, int size);

void buddy2_free(struct buddy2* self, int offset);

int buddy2_size(struct buddy2* self, int offset);

void buddy2_dump(struct buddy2* self);

#endif//__BUDDY2_H__

static int fixsize( int size )

{

size |= size >> 1;

size |= size >> 2;

size |= size >> 4;

size |= size >> 8;

size |= size >> 16;

return size+1;

}

void buddy2_destroy( struct buddy2* self) {

FREE(self);

}

int buddy2_size(struct buddy2* self, int offset) {

unsigned node_size, index = 0;

assert(self && offset >= 0 && offset < self->size);

node_size = 1;

for (index = offset + self->size - 1; self->longest[index] ; index = PARENT(index))

node_size *= 2;

return node_size;

}

void buddy2_dump(struct buddy2* self) {

char canvas[65];

int i,j;

unsigned node_size, offset;

if (self == NULL) {

printf("buddy2_dump: (struct buddy2*)self == NULL");

return;

}

if (self->size > 64) {

printf("buddy2_dump: (struct buddy2*)self is too big to dump");

return;

}

memset(canvas,‘_‘, sizeof(canvas));

node_size = self->size * 2;

for (i = 0; i < 2 * self->size - 1; ++i) {

if ( IS_POWER_OF_2(i+1) )

node_size /= 2;

if ( self->longest[i] == 0 ) {

if (i >=  self->size - 1) {

canvas[i - self->size + 1] = ‘*‘;

}

else if (self->longest[LEFT_LEAF(i)] && self->longest[RIGHT_LEAF(i)]) {

offset = (i+1) * node_size - self->size;

for (j = offset; j < offset + node_size; ++j)

canvas[j] = ‘*‘;

}

}

}

canvas[self->size] = ‘\0‘;

puts(canvas);

}

//#include "buddy2.h"

#include <stdio.h>

int main() {

char cmd[80];

int arg;

struct buddy2* buddy = buddy2_new(32);

buddy2_dump(buddy);

for (;;) {

scanf("%s %d", cmd, &arg);

if (strcmp(cmd, "alloc") == 0) {

printf("[email protected]%d\n", buddy2_alloc(buddy, arg));

buddy2_dump(buddy);

} else if (strcmp(cmd, "free") == 0) {

buddy2_free(buddy, arg);

buddy2_dump(buddy);

} else if (strcmp(cmd, "size") == 0) {

printf("size: %d\n", buddy2_size(buddy, arg));

buddy2_dump(buddy);

} else

buddy2_dump(buddy);

}

}

////////////////////////////////////////////////////////////////

#elif method == 0x02

//start from here

#ifndef BUDDY_MEMORY_ALLOCATION_H

#define BUDDY_MEMORY_ALLOCATION_H

struct buddy;

struct buddy * buddy_new(int level);

void buddy_delete(struct buddy *);

int buddy_alloc(struct buddy *, int size);

void buddy_free(struct buddy *, int offset);

int buddy_size(struct buddy *, int offset);

void buddy_dump(struct buddy *);

#endif

//#include "buddy.h"

#include <stdio.h>

#include <stdlib.h>

#include <stdint.h>

#include <assert.h>

#include <string.h>

#define NODE_UNUSED    0

#define NODE_USED      1

#define NODE_SPLIT     2

#define NODE_FULL      3

struct buddy {

int level;

uint8_t tree[1];

};

struct buddy * buddy_new( int level )

{

int size = 1 << level;

//printf( "level = %d.\r\n", level );

//printf( "size = %d.\r\n", size );

//printf( "sizeof(struct buddy) = %d.\r\n", sizeof(struct buddy) );

//printf( "sizeof(uint8_t) = %d.\r\n", sizeof(uint8_t) );

struct buddy *self = malloc(sizeof(struct buddy) + sizeof(uint8_t) * (size * 2 - 2));

//printf( "(sizeof(struct buddy) + sizeof(uint8_t) * (size * 2 - 2)) = %d.\r\n", (sizeof(struct buddy) + sizeof(uint8_t) * (size * 2 - 2)) );

//printf( "self = 0x%x.\r\n", self );

self->level = level;

//printf( "self->level = 0x%x.\r\n", self->level );

//printf( "&self->level = 0x%x.\r\n", &self->level );

//printf( "&self->tree = 0x%x.\r\n", &self->tree );

//printf( "self->tree = 0x%x.\r\n", self->tree );

memset( self->tree, NODE_UNUSED, size*2-1 );

return self;

}

void buddy_delete( struct buddy * self )

{

free(self);

}

//inline

static int is_pow_of_2( uint32_t x )

{

return !(x & (x-1));

}

//看一个数是否是2的power,2的n次幂

//即0 1 2 4 8 16 32 64 ...

//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;

//printf( "index = %d.\r\n", index );

//printf( "level = %d.\r\n", level );

//printf( "max_level = %d.\r\n", max_level );

ret = ((index + 1) - (1 << level)) << (max_level - level);

//printf( "ret = %d.\r\n", ret );

return ret;

}

//标记父母函数

static void _mark_parent( struct buddy * self, int index )

{

for( ; ; ){

//printf( "index = %d.\r\n", index );

int buddy = index - 1 + (index & 1) * 2;

//printf( "buddy = %d.\r\n", buddy );

//找出自己的兄弟

if( buddy > 0 && (self->tree[buddy] == NODE_USED || self->tree[buddy] == NODE_FULL) ){

//不是根节点 并且 兄弟节点使用了或者兄弟节点满了

//那么就要标记父亲节点

index = (index + 1) / 2 - 1;

//找到父亲节点的索引号

self->tree[index] = NODE_FULL;

//父亲节点置为满

}else{

//否则,还没满,不用管,维持原状就好了

return;

}

}

}

int buddy_alloc( struct buddy * self, int s )

{

int size, length, index, level;

if( s == 0 ){

size = 1;

}else{

size = (int)next_pow_of_2(s);

}

length = 1 << self->level;

if( size > length ){

return -1;

}

index = 0;

level = 0;

//printf( "size = %d.\r\n", size );

//printf( "length = %d.\r\n", length );

while( index >= 0 ){

if( size == length ){

//printf( "index.2 = %d.\r\n", index );

//printf( "self.2 = 0x%x.\r\n", self );

if( self->tree[index] == NODE_UNUSED ){

self->tree[index] = NODE_USED;

_mark_parent(self, index);

return _index_offset(index, level, self->level);

}

}else{

//size < length

switch( self->tree[index] )

{

case NODE_USED:

case NODE_FULL:

//已经使用或者已经满了

break;

case NODE_UNUSED:

//split first

//第一步 裂开 前提是父节点没有被使用 才可以裂开

self->tree[index] = NODE_SPLIT;

//父节点置为裂开状态    (2)

self->tree[index*2+1] = NODE_UNUSED;

//左孩子置为未使用状态  (0)

self->tree[index*2+2] = NODE_UNUSED;

//右孩子置为未使用状态  (0)

//printf( "index.0 = %d.\r\n", index );

//printf( "self = 0x%x.\r\n", self );

//printf( "self->tree[index] = %d.\r\n", self->tree[index] );

//printf( "&self->tree[index] = 0x%x.\r\n", &self->tree[index] );

//printf( "self->tree[index] = %d.\r\n", self->tree[index*2+1] );

//printf( "self->tree[index] = %d.\r\n", self->tree[index*2+2] );

//注意没有break

default:

index = index * 2 + 1;

//索引指向左孩子

length /= 2;

//长度缩小一半

level++;

//搜索层级加1 即指向下一层

//printf( "index.1 = %d.\r\n", index );

//printf( "length = %d.\r\n", length );

//printf( "level = %d.\r\n", level );

continue;

//注意没有break

}

}

//printf( "index.2 = %d.\r\n", index );

if( index & 1 ){

++index;

continue;

}

for( ; ; ){

printf( "index.2 = %d.\r\n", index );

level--;

length *= 2;

index = (index+1)/2 -1;

//父亲

//左边树搜索完没找到 那么就到右子树去搜索

if( index < 0 ){

return -1;

}

if( index & 1 ){

//父亲是左孩子,指向父亲的兄弟,即右孩子

++index;

break;

}

}

}

return -1;

}

static void _combine( struct buddy *self, int index )

{

for( ; ; ){

int buddy = index - 1 + (index & 1) * 2;

if( buddy < 0 || self->tree[buddy] != NODE_UNUSED ){

self->tree[index] = NODE_UNUSED;

while( ((index = (index + 1) / 2 - 1) >= 0) && self->tree[index] == NODE_FULL ){

self->tree[index] = NODE_SPLIT;

}

return;

}

index = (index + 1) / 2 - 1;

}

}

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;

}

}

void buddy_dump(struct buddy * self)

{

_dump(self, 0 , 0);

printf("\n");

}

static int test_alloc( struct buddy *b, int sz )

{

printf("\r\nstart alloc.\r\n");

int r = buddy_alloc(b, sz);

printf("alloc %d (sz= %d).\r\n\r\n",r,sz);

buddy_dump(b);

return r;

}

static void test_free( struct buddy *b, int addr )

{

printf( "free %d.\r\n", addr );

buddy_free( b, addr );

buddy_dump(b);

}

static void test_size(struct buddy *b, int addr)

{

int s = buddy_size(b,addr);

printf( "size addr = %d, (sz = %d).\r\n", addr, s );

}

//buddy 伙伴算法的简单实现

//只要看明白了这个c程序,就可以明白linux下的伙伴算法

void dump_array( unsigned char *p, int cnt )

{

int i = 0x00;

//printf( "p = %x.\r\n", p );

//printf( "cnt = %d.\r\n", cnt );

for( ; cnt; cnt-- ){

if( p[i] ){

printf( "p[%d] = 0x%x.\r\n", i, p[i] );

}

i++;

}

}

int main( void )

{

struct buddy * b;

int m1, m2, m3, m4, m5, m6;

b = buddy_new(3);

buddy_dump(b);

//dump_array( &b->tree[0], 32 );

m1 = test_alloc(b,2);

test_size(b,m1);

dump_array( &b->tree[0], 16 );

m2 = test_alloc(b,1);

test_size(b,m2);

dump_array( &b->tree[0], 16 );

m3 = test_alloc(b,2);

test_size(b,m3);

dump_array( &b->tree[0], 16 );

m4 = test_alloc(b,1);

test_size(b,m4);

dump_array( &b->tree[0], 16 );

m5 = test_alloc(b,2);

test_size(b,m5);

dump_array( &b->tree[0], 16 );

#if 0

m2 = test_alloc(b,9);

test_size(b,m2);

m3 = test_alloc(b,3);

test_size(b,m3);

m4 = test_alloc(b,7);

test_free(b,m3);

test_free(b,m1);

test_free(b,m4);

test_free(b,m2);

m5 = test_alloc(b,32);

test_free(b,m5);

m6 = test_alloc(b,0);

test_free(b,m6);

buddy_delete(b);

#endif

return 0;

}

#endif

#if 0

## Buddy Memory Allocation

A simple buddy memory allocation library .

See test.c for detail use.

## Question ?

* 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)

.Phony : all clean

all : test

test : test.c buddy.c

gcc -g -Wall -o [email protected] $^

clean :

rm -f test test.exe

#endif

时间: 2024-10-25 11:57:31

一个程序明白buddy算法的相关文章

(小说)那些年,那些事——一个程序员的奋斗史

转自:http://blog.csdn.net/x283930450/article/details/9072223 第01章    段伏枥,一个瘦小,矮小,根本和“帅”这个字粘不上任何关系的普通人 .名字的来源在于其多读了几年书的老爹,总抱着有一天要出书出名乃至于名流千古的 美好理想,但可惜现实总是给予他无情的而又现实的打击,于是就将理想寄望于自己的 儿子,起了个“伏枥”的名,寓意为“老骥伏枥,志在千里”,表达自己不到黄河不死 心的良好的愿望.     只可惜段伏枥这家伙完美地遗传了来自于老爹

从前有一个程序员,成天写代码,后来,他屎了。。。

从前有一个程序员,成天写代码,后来,他屎了 1.一门可以靠手艺混饭的专业 你好,非常荣幸能够步入改变世界的软件开发行业,接下来我们聊点正经的.回首近7-8年来的时光,发现自己可能将要走向程序员这条道路的时候最早可以追溯到2008年高考完填写志愿,那时候分数所迫,二本学校的好专业都上不了,我就想有什么专业是可以不靠学校名声而靠自己努力成就一番霸业的?思来想去选择了–计算机,作为第二志愿...显然那时候会计这个专业更火一些. 入学一年以后我有了自己第一台笔记本电脑,然而第一个装上的应用程序居然就是魔

1014 C语言文法定义与C程序的推导过程 程序:冒泡算法C程序(语法树)

1014 C语言文法定义与C程序的推导过程  程序:冒泡算法C程序(语法树)1 阅读并理解提供给大家的C语言文法文件. 2 参考该文件写出一个自己好理解版的现实版的完整版的C语言文法. 3 给出一段C程序,画出用上述文法产生这段C程序的完整语法树. 程序:冒泡算法C程序 点此文字查看原图(完整图片) 1 #include <stdio.h> 2 3 main() 4 { 5 int i,j,temp; 6 int a[10]; 7 8 for(i=0;i<10;i++) 9 scanf

CSDN日报20170318——《一个程序员的五年工作总结》

[程序人生]一个程序员的五年工作总结 作者:Programmer_Zhou 三月的重庆到处弥漫着浓浓的春味,在这个春暖花开的季节里,人们在闲暇的时间都忙着踏青和春游."一年之计在于春",春天是赏花旅游的季节,春天更是为未来作打算.定计划的时候.在2017年的春天,我做出了人生中的一个重要决定:离开工作近五年的ZTE(中兴通讯),去开启新的人生征程.最近我在罗辑思维的得到APP上订阅了薛兆丰老师的"北大经济学课"专栏,我认为他说的一句话特别有道理,这句话的大意是:&q

第一次自己去做一个程序,而不是照着书本上的代码打程序。

我之前想过用窗体做这个关于运算程序出来,因为那样可以让用户更加一目了然,更加方便的使用.但是一直在研究了好久之后,发现不知道该怎么样让用户在点击+-*/按钮的时候能够自动列出算式以及自动运用于计算.所以最终还是选择了用控制台应用程序来做. 这个程序大概是可以应用于小学,让低年级的小学生自己在电脑上做作业,既能够开发学生的思维,也可以借助小学生对电脑的兴趣来让他们对学习动脑更加努力. 设计思路大概就是运用之前学过树上的加法随机数运算,改变运算的规律,算法.运用计算机的计算功能以及if.else语句

连载《一个程序猿的生命周期》- 30、争取内蒙区的市场销售

一个程序猿的生命周期 微信平台 口    号:职业交流,职业规划:面对现实,用心去交流.感悟.  公众号:iterlifetime二维码:  百木-ITer职业交流奋斗 群:141588103 来公司的时候只不过是一名最普通的员工,尽管招来的时候老板承诺是负责项目团队.心里明白老板的用意,需要有一个过度期.但是,并不妨碍我对公司细致入微的观察,包括对人的观察,确实有些微妙的关系,却用语言无法准备的描述当时的感受. 在<22.缺了一条腿的公司>也大概描述了公司的情况,公司的业务或者说是市场.销售

每一个程序员都应当了解的11句话

每一个程序员都应当了解的11句话,你最同意哪一句? 1. 技术只是解决问题的选择,而不是解决问题的根本 我们可以因为掌握了最新的 JavaScript 框架 ahem.Angular 的 IoC 容器技术或者某些编程语言甚至操作系统而欢欣雀跃,但是这些东西并不是作为程序员的我们用来解决问题的根本——它们只是用于帮助我们解决问题的简单工具. 我们必须非常谨慎,不要对某项正好喜欢或者正好很火的特定技术走火入魔.否则,我们将进入这样的思维怪圈:把掌握的那项技术比做是锤子,在思考问题时,会自然的把所有的

一个程序员的十年总结

展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告 走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过的10年的路程,有些心得体会你可以借鉴一下,觉得说得有道理的你就接纳,觉得说得没道理的,你就抛弃,以下是我发自内心的,给大家的忠告,特别是针对那些小弟弟妹妹们. 01. 自己的户口档案.养老保险.医疗保险.住房公积金一定要保管好.由于程序员行业每年跳槽一次,我不隐瞒大家,我至少换过5个以上的单位,这期间

从1.5k到18k, 一个程序员的5年成长之路

http://blog.csdn.net/lgg201/article/details/8637763 昨天收到了心仪企业的口头offer, 回首当初什么都不会开始学编程, 到现在恰好五年. 整天在社区晃悠, 看了不少的总结, 在这个时间点, 我也写一份自己的总结吧. 我一直在社区分享, 所以, 这篇总结也是本着一种分享的态度, 希望相比我还年轻的同学们, 可以从中找到一些让自己成长更快的文字. 先介绍下背景:1. 2008年3月开始学习编程, 目前2013年3月;2. 2009年6月计算机专业