⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_bestfit_alloc.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * "Address order best fit" specific callbacks.                              *\*                                                                           */static voidaobf_link_free_block(Allctr_t *allctr, Block_t *block){    BFAllctr_t *bfallctr = (BFAllctr_t *) allctr;    RBTree_t *blk = (RBTree_t *) block;    Uint blk_sz = BLK_SZ(blk);    blk->flags	= 0;    blk->left	= NULL;    blk->right	= NULL;    if (!bfallctr->root) {	blk->parent = NULL;	SET_BLACK(blk);	bfallctr->root = blk;    }    else {	RBTree_t *x = bfallctr->root;	while (1) {	    Uint size;	    size = BLK_SZ(x);	    if (blk_sz < size || (blk_sz == size && blk < x)) {		if (!x->left) {		    blk->parent = x;		    x->left = blk;		    break;		}		x = x->left;	    }	    else {		if (!x->right) {		    blk->parent = x;		    x->right = blk;		    break;		}		x = x->right;	    }	}	/* Insert block into size tree */	RBT_ASSERT(blk->parent);	SET_RED(blk);	if (IS_RED(blk->parent))	    tree_insert_fixup(bfallctr, blk);    }#ifdef HARD_DEBUG    check_tree(bfallctr, 0);#endif}#if 0 /* tree_delete() is directly used instead */static voidaobf_unlink_free_block(Allctr_t *allctr, Block_t *block){    tree_delete(allctr, block);}#endifstatic Block_t *aobf_get_free_block(Allctr_t *allctr, Uint size){    BFAllctr_t *bfallctr = (BFAllctr_t *) allctr;    RBTree_t *x = bfallctr->root;    RBTree_t *blk = NULL;    Uint blk_sz;    while (x) {	blk_sz = BLK_SZ(x);	if (blk_sz < size) {	    x = x->right;	}	else {	    blk = x;	    x = x->left;	}    }        if (!blk)	return NULL;#ifdef HARD_DEBUG    ASSERT(blk == check_tree(bfallctr, size));#endif    aobf_unlink_free_block(allctr, (Block_t *) blk);    return (Block_t *) blk;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * "Best fit" specific callbacks.                                            *\*                                                                           */static voidbf_link_free_block(Allctr_t *allctr, Block_t *block){    BFAllctr_t *bfallctr = (BFAllctr_t *) allctr;    RBTree_t *blk = (RBTree_t *) block;    Uint blk_sz = BLK_SZ(blk);    SET_TREE_NODE(blk);    blk->flags	= 0;    blk->left	= NULL;    blk->right	= NULL;    if (!bfallctr->root) {	blk->parent = NULL;	SET_BLACK(blk);	bfallctr->root = blk;    }    else {	RBTree_t *x = bfallctr->root;	while (1) {	    Uint size;	    size = BLK_SZ(x);	    if (blk_sz == size) {		SET_LIST_ELEM(blk);		LIST_NEXT(blk) = LIST_NEXT(x);		LIST_PREV(blk) = x;		if (LIST_NEXT(x))		    LIST_PREV(LIST_NEXT(x)) = blk;		LIST_NEXT(x) = blk;		return; /* Finnished */	    }	    else if (blk_sz < size) {		if (!x->left) {		    blk->parent = x;		    x->left = blk;		    break;		}		x = x->left;	    }	    else {		if (!x->right) {		    blk->parent = x;		    x->right = blk;		    break;		}		x = x->right;	    }	}	RBT_ASSERT(blk->parent);	SET_RED(blk);	if (IS_RED(blk->parent))	    tree_insert_fixup(bfallctr, blk);    }    SET_TREE_NODE(blk);    LIST_NEXT(blk) = NULL;#ifdef HARD_DEBUG    check_tree(bfallctr, 0);#endif}static ERTS_INLINE voidbf_unlink_free_block(Allctr_t *allctr, Block_t *block){    BFAllctr_t *bfallctr = (BFAllctr_t *) allctr;    RBTree_t *x = (RBTree_t *) block;    if (IS_LIST_ELEM(x)) {	/* Remove from list */	ASSERT(LIST_PREV(x));	LIST_NEXT(LIST_PREV(x)) = LIST_NEXT(x);	if (LIST_NEXT(x))	    LIST_PREV(LIST_NEXT(x)) = LIST_PREV(x);    }    else if (LIST_NEXT(x)) {	/* Replace tree node by next element in list... */	ASSERT(BLK_SZ(LIST_NEXT(x)) == BLK_SZ(x));	ASSERT(IS_TREE_NODE(x));	ASSERT(IS_LIST_ELEM(LIST_NEXT(x)));#ifdef HARD_DEBUG	check_tree(bfallctr, 0);#endif	replace(&bfallctr->root, x, LIST_NEXT(x));#ifdef HARD_DEBUG	check_tree(bfallctr, 0);#endif    }    else {	/* Remove from tree */	tree_delete(allctr, block);    }    DESTROY_LIST_ELEM(x);}static Block_t *bf_get_free_block(Allctr_t *allctr, Uint size){    BFAllctr_t *bfallctr = (BFAllctr_t *) allctr;    RBTree_t *x = bfallctr->root;    RBTree_t *blk = NULL;    Uint blk_sz;    while (x) {	blk_sz = BLK_SZ(x);	if (blk_sz < size) {	    x = x->right;	}	else {	    blk = x;	    if (blk_sz == size)		break;	    x = x->left;	}    }        if (!blk)	return NULL;    ASSERT(IS_TREE_NODE(blk));#ifdef HARD_DEBUG    {	RBTree_t *ct_blk = check_tree(bfallctr, size);	ASSERT(BLK_SZ(ct_blk) == BLK_SZ(blk));    }#endif    /* Use next block if it exist in order to avoid replacing       the tree node */    blk = LIST_NEXT(blk) ? LIST_NEXT(blk) : blk;    bf_unlink_free_block(allctr, (Block_t *) blk);    return (Block_t *) blk;}/* * info_options() */static struct {    Eterm as;    Eterm aobf;    Eterm bf;#ifdef DEBUG    Eterm end_of_atoms;#endif} am;static void ERTS_INLINE atom_init(Eterm *atom, char *name){    *atom = am_atom_put(name, strlen(name));}#define AM_INIT(AM) atom_init(&am.AM, #AM)static voidinit_atoms(void){#ifdef DEBUG    Eterm *atom;#endif    if (atoms_initialized)	return;#ifdef DEBUG    for (atom = (Eterm *) &am; atom <= &am.end_of_atoms; atom++) {	*atom = THE_NON_VALUE;    }#endif    AM_INIT(as);    AM_INIT(aobf);    AM_INIT(bf);#ifdef DEBUG    for (atom = (Eterm *) &am; atom < &am.end_of_atoms; atom++) {	ASSERT(*atom != THE_NON_VALUE);    }#endif    atoms_initialized = 1;}#define bld_uint	erts_bld_uint#define bld_cons	erts_bld_cons#define bld_tuple	erts_bld_tuplestatic ERTS_INLINE voidadd_2tup(Uint **hpp, Uint *szp, Eterm *lp, Eterm el1, Eterm el2){    *lp = bld_cons(hpp, szp, bld_tuple(hpp, szp, 2, el1, el2), *lp);}static Eterminfo_options(Allctr_t *allctr,	     char *prefix,	     int *print_to_p,	     void *print_to_arg,	     Uint **hpp,	     Uint *szp){    BFAllctr_t *bfallctr = (BFAllctr_t *) allctr;    Eterm res = THE_NON_VALUE;    if (print_to_p) {	erts_print(*print_to_p,		   print_to_arg,		   "%sas: %s\n",		   prefix,		   bfallctr->address_order ? "aobf" : "bf");    }    if (hpp || szp) {		if (!atoms_initialized)	    erl_exit(1, "%s:%d: Internal error: Atoms not initialized",		     __FILE__, __LINE__);;	res = NIL;	add_2tup(hpp, szp, &res,		 am.as,		 bfallctr->address_order ? am.aobf : am.bf);    }    return res;}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * NOTE:  erts_bfalc_test() is only supposed to be used for testing.         * *                                                                           * * Keep alloc_SUITE_data/allocator_test.h updated if changes are made        * * to erts_bfalc_test()                                                      *\*                                                                           */unsigned longerts_bfalc_test(unsigned long op, unsigned long a1, unsigned long a2){    switch (op) {    case 0x200:	return (unsigned long) ((BFAllctr_t *) a1)->address_order;    case 0x201:	return (unsigned long) ((BFAllctr_t *) a1)->root;    case 0x202:	return (unsigned long) ((RBTree_t *) a1)->parent;    case 0x203:	return (unsigned long) ((RBTree_t *) a1)->left;    case 0x204:	return (unsigned long) ((RBTree_t *) a1)->right;    case 0x205:	return (unsigned long) ((RBTreeList_t *) a1)->next;    case 0x206:	return (unsigned long) IS_BLACK((RBTree_t *) a1);    case 0x207:	return (unsigned long) IS_TREE_NODE((RBTree_t *) a1);    default:	ASSERT(0); return ~((unsigned long) 0);    }}/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Debug functions                                                           *\*                                                                           */#ifdef HARD_DEBUG#define IS_LEFT_VISITED(FB)	((FB)->flags & LEFT_VISITED_FLG)#define IS_RIGHT_VISITED(FB)	((FB)->flags & RIGHT_VISITED_FLG)#define SET_LEFT_VISITED(FB)	((FB)->flags |= LEFT_VISITED_FLG)#define SET_RIGHT_VISITED(FB)	((FB)->flags |= RIGHT_VISITED_FLG)#define UNSET_LEFT_VISITED(FB)	((FB)->flags &= ~LEFT_VISITED_FLG)#define UNSET_RIGHT_VISITED(FB)	((FB)->flags &= ~RIGHT_VISITED_FLG)#if 0#  define PRINT_TREE#else#  undef PRINT_TREE#endif#ifdef PRINT_TREEstatic void print_tree(BFAllctr_t *);#endif/* * Checks that the order between parent and children are correct, * and that the Red-Black Tree properies are satisfied. if size > 0, * check_tree() returns a node that satisfies "best fit" resp. * "address order best fit". * * The Red-Black Tree properies are: *   1. Every node is either red or black. *   2. Every leaf (NIL) is black. *   3. If a node is red, then both its children are black. *   4. Every simple path from a node to a descendant leaf *      contains the same number of black nodes. */static RBTree_t *check_tree(BFAllctr_t *bfallctr, Uint size){    RBTree_t *res = NULL;    Sint blacks;    Sint curr_blacks;    RBTree_t *x;#ifdef PRINT_TREE    print_tree(bfallctr);#endif    if (!bfallctr->root)	return res;    x = bfallctr->root;    ASSERT(IS_BLACK(x));    ASSERT(!x->parent);    curr_blacks = 1;    blacks = -1;    while (x) {	if (!IS_LEFT_VISITED(x)) {	    SET_LEFT_VISITED(x);	    if (x->left) {		x = x->left;		if (IS_BLACK(x))		    curr_blacks++;		continue;	    }	    else {		if (blacks < 0)		    blacks = curr_blacks;		ASSERT(blacks == curr_blacks);	    }	}	if (!IS_RIGHT_VISITED(x)) {	    SET_RIGHT_VISITED(x);	    if (x->right) {		x = x->right;		if (IS_BLACK(x))		    curr_blacks++;		continue;	    }	    else {		if (blacks < 0)		    blacks = curr_blacks;		ASSERT(blacks == curr_blacks);	    }	}	if (IS_RED(x)) {	    ASSERT(IS_BLACK(x->right));	    ASSERT(IS_BLACK(x->left));	}	ASSERT(x->parent || x == bfallctr->root);	if (x->left) {	    ASSERT(x->left->parent == x);	    if (bfallctr->address_order) {		ASSERT(BLK_SZ(x->left) < BLK_SZ(x)		       || (BLK_SZ(x->left) == BLK_SZ(x) && x->left < x));	    }	    else {		ASSERT(IS_TREE_NODE(x->left));		ASSERT(BLK_SZ(x->left) < BLK_SZ(x));	    }	}	if (x->right) {	    ASSERT(x->right->parent == x);	    if (bfallctr->address_order) {		ASSERT(BLK_SZ(x->right) > BLK_SZ(x)		       || (BLK_SZ(x->right) == BLK_SZ(x) && x->right > x));	    }	    else {		ASSERT(IS_TREE_NODE(x->right));		ASSERT(BLK_SZ(x->right) > BLK_SZ(x));	    }	}	if (size && BLK_SZ(x) >= size) {	    if (bfallctr->address_order) {		if (!res		    || BLK_SZ(x) < BLK_SZ(res)		    || (BLK_SZ(x) == BLK_SZ(res) && x < res))		    res = x;	    }	    else {		if (!res || BLK_SZ(x) < BLK_SZ(res))		    res = x;	    }	}	UNSET_LEFT_VISITED(x);	UNSET_RIGHT_VISITED(x);	if (IS_BLACK(x))	    curr_blacks--;	x = x->parent;    }    ASSERT(curr_blacks == 0);    UNSET_LEFT_VISITED(bfallctr->root);    UNSET_RIGHT_VISITED(bfallctr->root);    return res;}#ifdef PRINT_TREE#define INDENT_STEP 2#include <stdio.h>static voidprint_tree_aux(RBTree_t *x, int indent){    int i;    if (!x) {	for (i = 0; i < indent; i++) {	    putc(' ', stderr);	}	fprintf(stderr, "BLACK: nil\r\n");    }    else {	print_tree_aux(x->right, indent + INDENT_STEP);	for (i = 0; i < indent; i++) {	    putc(' ', stderr);	}	fprintf(stderr, "%s: sz=%lu addr=0x%lx\r\n",		IS_BLACK(x) ? "BLACK" : "RED",		BLK_SZ(x),		(Uint) x);	print_tree_aux(x->left,  indent + INDENT_STEP);    }}static voidprint_tree(BFAllctr_t *bfallctr){    char *type = bfallctr->address_order ? "Size-Adress" : "Size";    fprintf(stderr, " --- %s tree begin ---\r\n", type);    print_tree_aux(bfallctr->root, 0);    fprintf(stderr, " --- %s tree end ---\r\n", type);}#endif#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -