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

📄 erl_bestfit_alloc.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ *//* * Description:	A combined "address order best fit"/"best fit" allocator *              based on a Red-Black (binary search) Tree. The search, *              insert, and delete operations are all O(log n) operations *              on a Red-Black Tree. In the "address order best fit" case *              n equals number of free blocks, and in the "best fit" case *              n equals number of distinct sizes of free blocks. Red-Black *              Trees are described in "Introduction to Algorithms", by *              Thomas H. Cormen, Charles E. Leiserson, and *              Ronald L. Riverest. * *              This module is a callback-module for erl_alloc_util.c * * Author: 	Rickard Green */#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include "global.h"#define GET_ERL_BF_ALLOC_IMPL#include "erl_bestfit_alloc.h"#ifdef DEBUG#if 0#define HARD_DEBUG#endif#else#undef HARD_DEBUG#endif#define MIN_MBC_SZ		(16*1024)#define MIN_MBC_FIRST_FREE_SZ	(4*1024)#define TREE_NODE_FLG		(((Uint) 1) << 0)#define RED_FLG			(((Uint) 1) << 1)#ifdef HARD_DEBUG#  define LEFT_VISITED_FLG	(((Uint) 1) << 2)#  define RIGHT_VISITED_FLG	(((Uint) 1) << 3)#endif#define IS_TREE_NODE(N)		(((RBTree_t *) (N))->flags & TREE_NODE_FLG)#define IS_LIST_ELEM(N)		(!IS_TREE_NODE(((RBTree_t *) (N))))#define SET_TREE_NODE(N)	(((RBTree_t *) (N))->flags |= TREE_NODE_FLG)#define SET_LIST_ELEM(N)	(((RBTree_t *) (N))->flags &= ~TREE_NODE_FLG)#define IS_RED(N)		(((RBTree_t *) (N)) \				 && ((RBTree_t *) (N))->flags & RED_FLG)#define IS_BLACK(N)		(!IS_RED(((RBTree_t *) (N))))#define SET_RED(N)		(((RBTree_t *) (N))->flags |= RED_FLG)#define SET_BLACK(N)		(((RBTree_t *) (N))->flags &= ~RED_FLG)#undef ASSERT#define ASSERT ASSERT_EXPR#if 1#define RBT_ASSERT	ASSERT#else#define RBT_ASSERT(x)#endif#ifdef HARD_DEBUGstatic RBTree_t * check_tree(BFAllctr_t *, Uint);#endifstatic void tree_delete(Allctr_t *allctr, Block_t *del);/* Prototypes of callback functions *//* "address order best fit" specific callback functions */static Block_t *	aobf_get_free_block	(Allctr_t *, Uint);static void		aobf_link_free_block	(Allctr_t *, Block_t *);#define			aobf_unlink_free_block	tree_delete/* "best fit" specific callback functions */static Block_t *	bf_get_free_block	(Allctr_t *, Uint);static void		bf_link_free_block	(Allctr_t *, Block_t *);static ERTS_INLINE void	bf_unlink_free_block	(Allctr_t *, Block_t *);static Eterm		info_options		(Allctr_t *, char *, int *,						 void *, Uint **, Uint *);static void		init_atoms		(void);/* Types... */struct RBTree_t_ {    Block_t hdr;    Uint flags;    RBTree_t *parent;    RBTree_t *left;    RBTree_t *right;};typedef struct {    RBTree_t t;    RBTree_t *next;} RBTreeList_t;#define LIST_NEXT(N) (((RBTreeList_t *) (N))->next)#define LIST_PREV(N) (((RBTreeList_t *) (N))->t.parent)#ifdef DEBUG/* Destroy all tree fields */#define DESTROY_TREE_NODE(N)						\  sys_memset((void *) (((Block_t *) (N)) + 1),				\	     0xff,							\	     (sizeof(RBTree_t) - sizeof(Block_t)))/* Destroy all tree and list fields */#define DESTROY_LIST_ELEM(N)						\  sys_memset((void *) (((Block_t *) (N)) + 1),				\	     0xff,							\	     (sizeof(RBTreeList_t) - sizeof(Block_t)))#else#define DESTROY_TREE_NODE(N)#define DESTROY_LIST_ELEM(N)#endifstatic int atoms_initialized = 0;voiderts_bfalc_init(void){    atoms_initialized = 0;}Allctr_t *erts_bfalc_start(BFAllctr_t *bfallctr,		 BFAllctrInit_t *bfinit,		 AllctrInit_t *init){    BFAllctr_t nulled_state = {{0}};    /* {{0}} is used instead of {0}, in order to avoid (an incorrect) gcc       warning. gcc warns if {0} is used as initializer of a struct when       the first member is a struct (not if, for example, the third member       is a struct). */    Allctr_t *allctr = (Allctr_t *) bfallctr;    sys_memcpy((void *) bfallctr, (void *) &nulled_state, sizeof(BFAllctr_t));    bfallctr->address_order		= bfinit->ao;    allctr->mbc_header_size		= sizeof(Carrier_t);    allctr->min_mbc_size		= MIN_MBC_SZ;    allctr->min_mbc_first_free_size	= MIN_MBC_FIRST_FREE_SZ;    allctr->min_block_size		= (bfinit->ao					   ? sizeof(RBTree_t)					   : sizeof(RBTreeList_t));    allctr->vsn_str			= (bfinit->ao					   ? ERTS_ALC_AOBF_ALLOC_VSN_STR					   : ERTS_ALC_BF_ALLOC_VSN_STR);    /* Callback functions */    if (bfinit->ao) {	allctr->get_free_block		= aobf_get_free_block;	allctr->link_free_block		= aobf_link_free_block;	allctr->unlink_free_block	= aobf_unlink_free_block;    }    else {	allctr->get_free_block		= bf_get_free_block;	allctr->link_free_block		= bf_link_free_block;	allctr->unlink_free_block	= bf_unlink_free_block;    }    allctr->info_options		= info_options;    allctr->get_next_mbc_size		= NULL;    allctr->creating_mbc		= NULL;    allctr->destroying_mbc		= NULL;    allctr->init_atoms			= init_atoms;#ifdef ERTS_ALLOC_UTIL_HARD_DEBUG    allctr->check_block			= NULL;    allctr->check_mbc			= NULL;#endif    allctr->atoms_initialized		= 0;    if (!erts_alcu_start(allctr, init))	return NULL;    return allctr;}/* * Red-Black Tree operations needed */static ERTS_INLINE voidleft_rotate(RBTree_t **root, RBTree_t *x){    RBTree_t *y = x->right;    x->right = y->left;    if (y->left)	y->left->parent = x;    y->parent = x->parent;    if (!y->parent) {	RBT_ASSERT(*root == x);	*root = y;    }    else if (x == x->parent->left)	x->parent->left = y;    else {	RBT_ASSERT(x == x->parent->right);	x->parent->right = y;    }    y->left = x;    x->parent = y;}static ERTS_INLINE voidright_rotate(RBTree_t **root, RBTree_t *x){    RBTree_t *y = x->left;    x->left = y->right;    if (y->right)	y->right->parent = x;    y->parent = x->parent;    if (!y->parent) {	RBT_ASSERT(*root == x);	*root = y;    }    else if (x == x->parent->right)	x->parent->right = y;    else {	RBT_ASSERT(x == x->parent->left);	x->parent->left = y;    }    y->right = x;    x->parent = y;}/* * Replace node x with node y * NOTE: block header of y is not changed */static ERTS_INLINE voidreplace(RBTree_t **root, RBTree_t *x, RBTree_t *y){    if (!x->parent) {	RBT_ASSERT(*root == x);	*root = y;    }    else if (x == x->parent->left)	x->parent->left = y;    else {	RBT_ASSERT(x == x->parent->right);	x->parent->right = y;    }    if (x->left) {	RBT_ASSERT(x->left->parent == x);	x->left->parent = y;    }    if (x->right) {	RBT_ASSERT(x->right->parent == x);	x->right->parent = y;    }    y->flags	= x->flags;    y->parent	= x->parent;    y->right	= x->right;    y->left	= x->left;    DESTROY_TREE_NODE(x);}static voidtree_insert_fixup(BFAllctr_t *bfallctr, RBTree_t *blk){    RBTree_t *x = blk, *y;    /*     * Rearrange the tree so that it satisfies the Red-Black Tree properties     */    RBT_ASSERT(x != bfallctr->root && IS_RED(x->parent));    do {	/*	 * x and its parent are both red. Move the red pair up the tree	 * until we get to the root or until we can separate them.	 */	RBT_ASSERT(IS_RED(x));	RBT_ASSERT(IS_BLACK(x->parent->parent));	RBT_ASSERT(x->parent->parent);	if (x->parent == x->parent->parent->left) {	    y = x->parent->parent->right;	    if (IS_RED(y)) {		SET_BLACK(y);		x = x->parent;		SET_BLACK(x);		x = x->parent;		SET_RED(x);	    }	    else {		if (x == x->parent->right) {		    x = x->parent;		    left_rotate(&bfallctr->root, x);		}		RBT_ASSERT(x == x->parent->parent->left->left);		RBT_ASSERT(IS_RED(x));		RBT_ASSERT(IS_RED(x->parent));		RBT_ASSERT(IS_BLACK(x->parent->parent));		RBT_ASSERT(IS_BLACK(y));		SET_BLACK(x->parent);		SET_RED(x->parent->parent);		right_rotate(&bfallctr->root, x->parent->parent);		RBT_ASSERT(x == x->parent->left);		RBT_ASSERT(IS_RED(x));		RBT_ASSERT(IS_RED(x->parent->right));		RBT_ASSERT(IS_BLACK(x->parent));		break;	    }	}	else {	    RBT_ASSERT(x->parent == x->parent->parent->right);	    y = x->parent->parent->left;	    if (IS_RED(y)) {		SET_BLACK(y);		x = x->parent;		SET_BLACK(x);		x = x->parent;		SET_RED(x);	    }	    else {		if (x == x->parent->left) {		    x = x->parent;		    right_rotate(&bfallctr->root, x);		}		RBT_ASSERT(x == x->parent->parent->right->right);		RBT_ASSERT(IS_RED(x));		RBT_ASSERT(IS_RED(x->parent));		RBT_ASSERT(IS_BLACK(x->parent->parent));		RBT_ASSERT(IS_BLACK(y));		SET_BLACK(x->parent);		SET_RED(x->parent->parent);		left_rotate(&bfallctr->root, x->parent->parent);		RBT_ASSERT(x == x->parent->right);		RBT_ASSERT(IS_RED(x));		RBT_ASSERT(IS_RED(x->parent->left));		RBT_ASSERT(IS_BLACK(x->parent));		break;	    }	}    } while (x != bfallctr->root && IS_RED(x->parent));    SET_BLACK(bfallctr->root);}/* * The argument types of "Allctr_t *" and "Block_t *" have been * chosen since we then can use tree_delete() as unlink_free_block * callback function in the address order case. */static voidtree_delete(Allctr_t *allctr, Block_t *del){    BFAllctr_t *bfallctr = (BFAllctr_t *) allctr;    Uint spliced_is_black;    RBTree_t *x, *y, *z = (RBTree_t *) del;    RBTree_t null_x; /* null_x is used to get the fixup started when we			splice out a node without children. */    null_x.parent = NULL;#ifdef HARD_DEBUG    check_tree(bfallctr, 0);#endif    /* Remove node from tree... */    /* Find node to splice out */    if (!z->left || !z->right)	y = z;    else	/* Set y to z:s successor */	for(y = z->right; y->left; y = y->left);    /* splice out y */    x = y->left ? y->left : y->right;    spliced_is_black = IS_BLACK(y);    if (x) {	x->parent = y->parent;    }    else if (!x && spliced_is_black) {	x = &null_x;	x->flags = 0;	SET_BLACK(x);	x->right = x->left = NULL;	x->parent = y->parent;	y->left = x;    }    if (!y->parent) {	RBT_ASSERT(bfallctr->root == y);	bfallctr->root = x;    }    else if (y == y->parent->left)	y->parent->left = x;    else {	RBT_ASSERT(y == y->parent->right);	y->parent->right = x;    }    if (y != z) {	/* We spliced out the successor of z; replace z by the successor */	replace(&bfallctr->root, z, y);    }    if (spliced_is_black) {	/* We removed a black node which makes the resulting tree	   violate the Red-Black Tree properties. Fixup tree... */	while (IS_BLACK(x) && x->parent) {	    /*	     * x has an "extra black" which we move up the tree	     * until we reach the root or until we can get rid of it.	     *	     * y is the sibbling of x	     */	    if (x == x->parent->left) {		y = x->parent->right;		RBT_ASSERT(y);		if (IS_RED(y)) {		    RBT_ASSERT(y->right);		    RBT_ASSERT(y->left);		    SET_BLACK(y);		    RBT_ASSERT(IS_BLACK(x->parent));		    SET_RED(x->parent);		    left_rotate(&bfallctr->root, x->parent);		    y = x->parent->right;		}		RBT_ASSERT(y);		RBT_ASSERT(IS_BLACK(y));		if (IS_BLACK(y->left) && IS_BLACK(y->right)) {		    SET_RED(y);		    x = x->parent;		}		else {		    if (IS_BLACK(y->right)) {			SET_BLACK(y->left);			SET_RED(y);			right_rotate(&bfallctr->root, y);			y = x->parent->right;		    }		    RBT_ASSERT(y);		    if (IS_RED(x->parent)) {			SET_BLACK(x->parent);			SET_RED(y);		    }		    RBT_ASSERT(y->right);		    SET_BLACK(y->right);		    left_rotate(&bfallctr->root, x->parent);		    x = bfallctr->root;		    break;		}	    }	    else {		RBT_ASSERT(x == x->parent->right);		y = x->parent->left;		RBT_ASSERT(y);		if (IS_RED(y)) {		    RBT_ASSERT(y->right);		    RBT_ASSERT(y->left);		    SET_BLACK(y);		    RBT_ASSERT(IS_BLACK(x->parent));		    SET_RED(x->parent);		    right_rotate(&bfallctr->root, x->parent);		    y = x->parent->left;		}		RBT_ASSERT(y);		RBT_ASSERT(IS_BLACK(y));		if (IS_BLACK(y->right) && IS_BLACK(y->left)) {		    SET_RED(y);		    x = x->parent;		}		else {		    if (IS_BLACK(y->left)) {			SET_BLACK(y->right);			SET_RED(y);			left_rotate(&bfallctr->root, y);			y = x->parent->left;		    }		    RBT_ASSERT(y);		    if (IS_RED(x->parent)) {			SET_BLACK(x->parent);			SET_RED(y);		    }		    RBT_ASSERT(y->left);		    SET_BLACK(y->left);		    right_rotate(&bfallctr->root, x->parent);		    x = bfallctr->root;		    break;		}	    }	}	SET_BLACK(x);	if (null_x.parent) {	    if (null_x.parent->left == &null_x)		null_x.parent->left = NULL;	    else {		RBT_ASSERT(null_x.parent->right == &null_x);		null_x.parent->right = NULL;	    }	    RBT_ASSERT(!null_x.left);	    RBT_ASSERT(!null_x.right);	}	else if (bfallctr->root == &null_x) {	    bfallctr->root = NULL;	    RBT_ASSERT(!null_x.left);	    RBT_ASSERT(!null_x.right);	}    }    DESTROY_TREE_NODE(del);#ifdef HARD_DEBUG    check_tree(bfallctr, 0);#endif}

⌨️ 快捷键说明

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