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

📄 pool.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	t = B2T(b);	t->size = b->size;	t->magic0 = TAIL_MAGIC0;	t->magic1 = TAIL_MAGIC1;	return b;}/* getdsize: return the requested data size for an allocated block */static ulonggetdsize(Alloc *b){	Btail *t;	t = B2T(b);	return b->size - SHORT(t->datasize);}/* blocksetdsize: set the user data size of a block */static Alloc*blocksetdsize(Pool *p, Alloc *b, ulong dsize){	Btail *t;	uchar *q, *eq;	assert(b->size >= dsize2bsize(p, dsize));	assert(b->size - dsize < 0x10000);	t = B2T(b);	PSHORT(t->datasize, b->size - dsize);	q=(uchar*)_B2D(b)+dsize;	eq = (uchar*)t;	if(eq > q+4)		eq = q+4;	for(; q<eq; q++)		*q = datamagic[((ulong)(uintptr)q)%nelem(datamagic)];	return b;}/* trim: trim a block down to what is needed to hold dsize bytes of user data */static Alloc*trim(Pool *p, Alloc *b, ulong dsize){	ulong extra, bsize;	Alloc *frag;	bsize = dsize2bsize(p, dsize);	extra = b->size - bsize;	if(b->size - dsize >= 0x10000 ||	  (extra >= bsize>>2 && extra >= MINBLOCKSIZE && extra >= p->minblock)) {		blocksetsize(b, bsize);		frag = (Alloc*) B2NB(b);		antagonism {			memmark(frag, 0xF1, extra);		}		frag->magic = UNALLOC_MAGIC;		blocksetsize(frag, extra);		pooladd(p, frag);	}	b->magic = ALLOC_MAGIC;	blocksetdsize(p, b, dsize);	return b;}static Alloc*freefromfront(Pool *p, Alloc *b, ulong skip){	Alloc *bb;	skip = skip&~(p->quantum-1);	if(skip >= 0x1000 || (skip >= b->size>>2 && skip >= MINBLOCKSIZE && skip >= p->minblock)){		bb = (Alloc*)((uchar*)b+skip);		blocksetsize(bb, b->size-skip);		bb->magic = UNALLOC_MAGIC;		blocksetsize(b, skip);		b->magic = UNALLOC_MAGIC;		pooladd(p, b);		return bb;	}	return b;	}/* * Arena maintenance *//* arenasetsize: set arena size, updating tail */static voidarenasetsize(Arena *a, ulong asize){	Bhdr *atail;	a->asize = asize;	atail = A2TB(a);	atail->magic = ARENATAIL_MAGIC;	atail->size = 0;}/* poolnewarena: allocate new arena */static voidpoolnewarena(Pool *p, ulong asize){	Arena *a;	Arena *ap, *lastap;	Alloc *b;	LOG(p, "newarena %lud\n", asize);	if(p->cursize+asize > p->maxsize) {		if(poolcompactl(p) == 0){			LOG(p, "pool too big: %lud+%lud > %lud\n",				p->cursize, asize, p->maxsize);			werrstr("memory pool too large");		}		return;	}	if((a = p->alloc(asize)) == nil) {		/* assume errstr set by p->alloc */		return;	}	p->cursize += asize;	/* arena hdr */	a->magic = ARENA_MAGIC;	blocksetsize(a, sizeof(Arena));	arenasetsize(a, asize);	blockcheck(p, a);	/* create one large block in arena */	b = (Alloc*)A2B(a);	b->magic = UNALLOC_MAGIC;	blocksetsize(b, (uchar*)A2TB(a)-(uchar*)b);	blockcheck(p, b);	pooladd(p, b);	blockcheck(p, b);	/* sort arena into descending sorted arena list */	for(lastap=nil, ap=p->arenalist; ap > a; lastap=ap, ap=ap->down)		;	if(a->down = ap)	/* assign = */		a->down->aup = a;	if(a->aup = lastap)	/* assign = */		a->aup->down = a;	else		p->arenalist = a;	/* merge with surrounding arenas if possible */	/* must do a with up before down with a (think about it) */	if(a->aup)		arenamerge(p, a, a->aup);	if(a->down)		arenamerge(p, a->down, a);}/* blockresize: grow a block to encompass space past its end, possibly by *//* trimming it into two different blocks. */static voidblockgrow(Pool *p, Bhdr *b, ulong nsize){	if(b->magic == FREE_MAGIC) {		Alloc *a;		Bhdr *bnxt;		a = pooldel(p, (Free*)b);		blockcheck(p, a);		blocksetsize(a, nsize);		blockcheck(p, a);		bnxt = B2NB(a);		if(bnxt->magic == FREE_MAGIC)			a = blockmerge(p, a, bnxt);		blockcheck(p, a);		pooladd(p, a);	} else {		Alloc *a;		ulong dsize;		a = (Alloc*)b;		dsize = getdsize(a);		blocksetsize(a, nsize);		trim(p, a, dsize);	}}/* arenamerge: attempt to coalesce to arenas that might be adjacent */static Arena*arenamerge(Pool *p, Arena *bot, Arena *top){	Bhdr *bbot, *btop;	Btail *t;	blockcheck(p, bot);	blockcheck(p, top);	assert(bot->aup == top && top > bot);	if(p->merge == nil || p->merge(bot, top) == 0)		return nil;	/* remove top from list */	if(bot->aup = top->aup)	/* assign = */		bot->aup->down = bot;	else		p->arenalist = bot;		/* save ptrs to last block in bot, first block in top */	t = B2PT(A2TB(bot));	bbot = T2HDR(t);	btop = A2B(top);	blockcheck(p, bbot);	blockcheck(p, btop);	/* grow bottom arena to encompass top */	arenasetsize(bot, top->asize + ((uchar*)top - (uchar*)bot));	/* grow bottom block to encompass space between arenas */	blockgrow(p, bbot, (uchar*)btop-(uchar*)bbot);	blockcheck(p, bbot);	return bot;}/* dumpblock: print block's vital stats */static voiddumpblock(Pool *p, Bhdr *b){	ulong *dp;	ulong dsize;	uchar *cp;	dp = (ulong*)b;	p->print(p, "pool %s block %p\nhdr %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux\n",		p->name, b, dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], dp[6]);	if(b->size >= 1024*1024*1024)	/* tail pointer corrupt; printing tail will fault */		return;	dp = (ulong*)B2T(b);	p->print(p, "tail %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux | %.8lux %.8lux\n",		dp[-6], dp[-5], dp[-4], dp[-3], dp[-2], dp[-1], dp[0], dp[1]);	if(b->magic == ALLOC_MAGIC){		dsize = getdsize((Alloc*)b);		if(dsize >= b->size)	/* user data size corrupt */			return;		cp = (uchar*)_B2D(b)+dsize;		p->print(p, "user data ");		p->print(p, "%.2ux %.2ux %.2ux %.2ux  %.2ux %.2ux %.2ux %.2ux",			cp[-8], cp[-7], cp[-6], cp[-5], cp[-4], cp[-3], cp[-2], cp[-1]);		p->print(p, " | %.2ux %.2ux %.2ux %.2ux  %.2ux %.2ux %.2ux %.2ux\n",			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);	}}static voidprintblock(Pool *p, Bhdr *b, char *msg){	p->print(p, "%s\n", msg);	dumpblock(p, b);}static voidpanicblock(Pool *p, Bhdr *b, char *msg){	p->print(p, "%s\n", msg);	dumpblock(p, b);	p->panic(p, "pool panic");}/* blockcheck: ensure a block consistent with our expectations *//* should only be called when holding pool lock */static voidblockcheck(Pool *p, Bhdr *b){	Alloc *a;	Btail *t;	int i, n;	uchar *q, *bq, *eq;	ulong dsize;	switch(b->magic) {	default:		panicblock(p, b, "bad magic");	case FREE_MAGIC:	case UNALLOC_MAGIC:	 	t = B2T(b);		if(t->magic0 != TAIL_MAGIC0 || t->magic1 != TAIL_MAGIC1)			panicblock(p, b, "corrupt tail magic");		if(T2HDR(t) != b)			panicblock(p, b, "corrupt tail ptr");		break;	case DEAD_MAGIC:	 	t = B2T(b);		if(t->magic0 != TAIL_MAGIC0 || t->magic1 != TAIL_MAGIC1)			panicblock(p, b, "corrupt tail magic");		if(T2HDR(t) != b)			panicblock(p, b, "corrupt tail ptr");		n = getdsize((Alloc*)b);		q = _B2D(b);		q += 8;		for(i=8; i<n; i++)			if(*q++ != 0xDA)				panicblock(p, b, "dangling pointer write");		break;	case ARENA_MAGIC:		b = A2TB((Arena*)b);		if(b->magic != ARENATAIL_MAGIC)			panicblock(p, b, "bad arena size");		/* fall through */	case ARENATAIL_MAGIC:		if(b->size != 0)			panicblock(p, b, "bad arena tail size");		break;	case ALLOC_MAGIC:		a = (Alloc*)b;		if(a->size > 1024*1024*1024)			panicblock(p, b, "block too big");	 	t = B2T(b);		dsize = getdsize(a);		bq = (uchar*)_B2D(a)+dsize;		eq = (uchar*)t;		if(t->magic0 != TAIL_MAGIC0){			/* if someone wrote exactly one byte over and it was a NUL, we sometimes only complain. */			if((p->flags & POOL_TOLERANCE) && bq == eq && t->magic0 == 0)				printblock(p, b, "mem user overflow (magic0)");			else				panicblock(p, b, "corrupt tail magic0");		}		if(t->magic1 != TAIL_MAGIC1)			panicblock(p, b, "corrupt tail magic1");		if(T2HDR(t) != b)			panicblock(p, b, "corrupt tail ptr");		if(dsize2bsize(p, dsize)  > a->size)			panicblock(p, b, "too much block data");		if(eq > bq+4)			eq = bq+4;		for(q=bq; q<eq; q++){			if(*q != datamagic[((uintptr)q)%nelem(datamagic)]){				if(q == bq && *q == 0 && (p->flags & POOL_TOLERANCE)){					printblock(p, b, "mem user overflow");					continue;				}				panicblock(p, b, "mem user overflow");			}		}		break;	}}/* * compact an arena by shifting all the free blocks to the end. * assumes pool lock is held. */enum {	FLOATING_MAGIC = 0xCBCBCBCB,	/* temporarily neither allocated nor in the free tree */};static intarenacompact(Pool *p, Arena *a){	Bhdr *b, *wb, *eb, *nxt;	int compacted;	if(p->move == nil)		p->panic(p, "don't call me when pool->move is nil\n");	poolcheckarena(p, a);	eb = A2TB(a);	compacted = 0;	for(b=wb=A2B(a); b && b < eb; b=nxt) {		nxt = B2NB(b);		switch(b->magic) {		case FREE_MAGIC:			pooldel(p, (Free*)b);			b->magic = FLOATING_MAGIC;			break;		case ALLOC_MAGIC:			if(wb != b) {				memmove(wb, b, b->size);				p->move(_B2D(b), _B2D(wb));				compacted = 1;			}			wb = B2NB(wb);			break;		}	}	/*	 * the only free data is now at the end of the arena, pointed	 * at by wb.  all we need to do is set its size and get out.	 */	if(wb < eb) {		wb->magic = UNALLOC_MAGIC;		blocksetsize(wb, (uchar*)eb-(uchar*)wb);		pooladd(p, (Alloc*)wb);	}	return compacted;		}/* * compact a pool by compacting each individual arena. * 'twould be nice to shift blocks from one arena to the * next but it's a pain to code. */static intpoolcompactl(Pool *pool){	Arena *a;	int compacted;	if(pool->move == nil || pool->lastcompact == pool->nfree)		return 0;	pool->lastcompact = pool->nfree;	compacted = 0;	for(a=pool->arenalist; a; a=a->down)		compacted |= arenacompact(pool, a);	return compacted;}/*static intpoolcompactl(Pool*){	return 0;}*//* * Actual allocators *//*static void*_B2D(void *a){	return (uchar*)a+sizeof(Bhdr);}*/static void*B2D(Pool *p, Alloc *a){	if(a->magic != ALLOC_MAGIC)		p->panic(p, "B2D called on unworthy block");	return _B2D(a);}/*static void*_D2B(void *v){	Alloc *a;	a = (Alloc*)((uchar*)v-sizeof(Bhdr));	return a;}*/static Alloc*D2B(Pool *p, void *v){	Alloc *a;	ulong *u;	if((uintptr)v&(sizeof(ulong)-1))		v = (char*)v - ((uintptr)v&(sizeof(ulong)-1));	u = v;	while(u[-1] == ALIGN_MAGIC)		u--;	a = _D2B(u);	if(a->magic != ALLOC_MAGIC)		p->panic(p, "D2B called on non-block %p (double-free?)", v);	return a;}/* poolallocl: attempt to allocate block to hold dsize user bytes; assumes lock held */static void*poolallocl(Pool *p, ulong dsize){	ulong bsize;	Free *fb;	Alloc *ab;

⌨️ 快捷键说明

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