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

📄 pool.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	if(dsize < 0 || dsize >= 0x80000000UL){	/* for sanity, overflow */		werrstr("invalid allocation size");		return nil;	}	bsize = dsize2bsize(p, dsize);	fb = treelookupgt(p->freeroot, bsize);	if(fb == nil) {		poolnewarena(p, bsize2asize(p, bsize));		if((fb = treelookupgt(p->freeroot, bsize)) == nil) {			/* assume poolnewarena failed and set %r */			return nil;		}	}	ab = trim(p, pooldel(p, fb), dsize);	p->curalloc += ab->size;	antagonism {		memset(B2D(p, ab), 0xDF, dsize);	}	return B2D(p, ab);}/* poolreallocl: attempt to grow v to ndsize bytes; assumes lock held */static void*poolreallocl(Pool *p, void *v, ulong ndsize){	Alloc *a;	Bhdr *left, *right, *newb;	Btail *t;	ulong nbsize;	ulong odsize;	ulong obsize;	void *nv;	if(v == nil)	/* for ANSI */		return poolallocl(p, ndsize);	if(ndsize == 0) {		poolfreel(p, v);		return nil;	}	a = D2B(p, v);	blockcheck(p, a);	odsize = getdsize(a);	obsize = a->size;	/* can reuse the same block? */	nbsize = dsize2bsize(p, ndsize);	if(nbsize <= a->size) {	Returnblock:		if(v != _B2D(a))			memmove(_B2D(a), v, odsize);		a = trim(p, a, ndsize);		p->curalloc -= obsize;		p->curalloc += a->size;		v = B2D(p, a);		return v;	}	/* can merge with surrounding blocks? */	right = B2NB(a);	if(right->magic == FREE_MAGIC && a->size+right->size >= nbsize) {		a = blockmerge(p, a, right);		goto Returnblock;	}	t = B2PT(a);	left = T2HDR(t);	if(left->magic == FREE_MAGIC && left->size+a->size >= nbsize) {		a = blockmerge(p, left, a);		goto Returnblock;	}	if(left->magic == FREE_MAGIC && right->magic == FREE_MAGIC	&& left->size+a->size+right->size >= nbsize) {		a = blockmerge(p, blockmerge(p, left, a), right);		goto Returnblock;	}	if((nv = poolallocl(p, ndsize)) == nil)		return nil;	/* maybe the new block is next to us; if so, merge */	left = T2HDR(B2PT(a));	right = B2NB(a);	newb = D2B(p, nv);	if(left == newb || right == newb) {		if(left == newb || left->magic == FREE_MAGIC)			a = blockmerge(p, left, a);		if(right == newb || right->magic == FREE_MAGIC)			a = blockmerge(p, a, right);		assert(a->size >= nbsize);		goto Returnblock;	}	/* enough cleverness */	memmove(nv, v, odsize);	antagonism { 		memset((char*)nv+odsize, 0xDE, ndsize-odsize);	}	poolfreel(p, v);	return nv;}static void*alignptr(void *v, ulong align, long offset){	char *c;	ulong off;	c = v;	if(align){		off = (uintptr)c%align;		if(off != offset){			c += offset - off;			if(off > offset)				c += align;		}	}	return c;}/* poolspanallocl: allocate as described below; assumes pool locked */static void*poolallocalignl(Pool *p, ulong dsize, ulong align, long offset, ulong span){	ulong asize;	void *v;	char *c;	ulong *u;	int skip;	Alloc *b;	/*	 * allocate block	 * 	dsize bytes	 *	addr == offset (modulo align)	 *	does not cross span-byte block boundary	 *	 * to satisfy alignment, just allocate an extra	 * align bytes and then shift appropriately.	 * 	 * to satisfy span, try once and see if we're	 * lucky.  the second time, allocate 2x asize	 * so that we definitely get one not crossing	 * the boundary.	 */	if(align){		if(offset < 0)			offset = align - ((-offset)%align);		else			offset %= align;	}	asize = dsize+align;	v = poolallocl(p, asize);	if(v == nil)		return nil;	if(span && (uintptr)v/span != ((uintptr)v+asize)/span){		/* try again */		poolfreel(p, v);		v = poolallocl(p, 2*asize);		if(v == nil)			return nil;	}	/*	 * figure out what pointer we want to return	 */	c = alignptr(v, align, offset);	if(span && (uintptr)c/span != (uintptr)(c+dsize-1)/span){		c += span - (uintptr)c%span;		c = alignptr(c, align, offset);		if((uintptr)c/span != (uintptr)(c+dsize-1)/span){			poolfreel(p, v);			werrstr("cannot satisfy dsize %lud span %lud with align %lud+%ld", dsize, span, align, offset);			return nil;		}	}	skip = c - (char*)v;	/*	 * free up the skip bytes before that pointer	 * or mark it as unavailable.	 */	b = _D2B(v);	b = freefromfront(p, b, skip);	v = _B2D(b);	skip = c - (char*)v;	if(c > (char*)v){		u = v;		while(c >= (char*)u+sizeof(ulong))			*u++ = ALIGN_MAGIC;	}	trim(p, b, skip+dsize);	assert(D2B(p, c) == b);	antagonism { 		memset(c, 0xDD, dsize);	}	return c;}/* poolfree: free block obtained from poolalloc; assumes lock held */static voidpoolfreel(Pool *p, void *v){	Alloc *ab;	Bhdr *back, *fwd;	if(v == nil)	/* for ANSI */		return;	ab = D2B(p, v);	blockcheck(p, ab);	if(p->flags&POOL_NOREUSE){		int n;		ab->magic = DEAD_MAGIC;		n = getdsize(ab)-8;		if(n > 0)			memset((uchar*)v+8, 0xDA, n);		return;		}	p->nfree++;	p->curalloc -= ab->size;	back = T2HDR(B2PT(ab));	if(back->magic == FREE_MAGIC)		ab = blockmerge(p, back, ab);	fwd = B2NB(ab);	if(fwd->magic == FREE_MAGIC)		ab = blockmerge(p, ab, fwd);	pooladd(p, ab);}void*poolalloc(Pool *p, ulong n){	void *v;	p->lock(p);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	v = poolallocl(p, n);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	if(p->logstack && (p->flags & POOL_LOGGING)) p->logstack(p);	LOG(p, "poolalloc %p %lud = %p\n", p, n, v);	p->unlock(p);	return v;}void*poolallocalign(Pool *p, ulong n, ulong align, long offset, ulong span){	void *v;	p->lock(p);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	v = poolallocalignl(p, n, align, offset, span);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	if(p->logstack && (p->flags & POOL_LOGGING)) p->logstack(p);	LOG(p, "poolalignspanalloc %p %lud %lud %lud %ld = %p\n", p, n, align, span, offset, v);	p->unlock(p);	return v;}intpoolcompact(Pool *p){	int rv;	p->lock(p);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	rv = poolcompactl(p);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	LOG(p, "poolcompact %p\n", p);	p->unlock(p);	return rv;}void*poolrealloc(Pool *p, void *v, ulong n){	void *nv;	p->lock(p);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	nv = poolreallocl(p, v, n);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	if(p->logstack && (p->flags & POOL_LOGGING)) p->logstack(p);	LOG(p, "poolrealloc %p %p %ld = %p\n", p, v, n, nv);	p->unlock(p);	return nv;}voidpoolfree(Pool *p, void *v){	p->lock(p);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	poolfreel(p, v);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	if(p->logstack && (p->flags & POOL_LOGGING)) p->logstack(p);	LOG(p, "poolfree %p %p\n", p, v);	p->unlock(p);}/* * Return the real size of a block, and let the user use it.  */ulongpoolmsize(Pool *p, void *v){	Alloc *b;	ulong dsize;	p->lock(p);	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	if(v == nil)	/* consistency with other braindead ANSI-ness */		dsize = 0;	else {		b = D2B(p, v);		dsize = (b->size&~(p->quantum-1)) - sizeof(Bhdr) - sizeof(Btail);		assert(dsize >= getdsize(b));		blocksetdsize(p, b, dsize);	}	paranoia {		poolcheckl(p);	}	verbosity {		pooldumpl(p);	}	if(p->logstack && (p->flags & POOL_LOGGING)) p->logstack(p);	LOG(p, "poolmsize %p %p = %ld\n", p, v, dsize);	p->unlock(p);	return dsize;}/* * Debugging  */static voidpoolcheckarena(Pool *p, Arena *a){	Bhdr *b;	Bhdr *atail;	atail = A2TB(a);	for(b=a; b->magic != ARENATAIL_MAGIC && b<atail; b=B2NB(b))		blockcheck(p, b);	blockcheck(p, b);	if(b != atail)		p->panic(p, "found wrong tail");}static voidpoolcheckl(Pool *p){	Arena *a;	for(a=p->arenalist; a; a=a->down)		poolcheckarena(p, a);	if(p->freeroot)		checktree(p->freeroot, 0, 1<<30);}voidpoolcheck(Pool *p){	p->lock(p);	poolcheckl(p);	p->unlock(p);}voidpoolblockcheck(Pool *p, void *v){	if(v == nil)		return;	p->lock(p);	blockcheck(p, D2B(p, v));	p->unlock(p);}static voidpooldumpl(Pool *p){	Arena *a;	p->print(p, "pool %p %s\n", p, p->name);	for(a=p->arenalist; a; a=a->down)		pooldumparena(p, a);}voidpooldump(Pool *p){	p->lock(p);	pooldumpl(p);	p->unlock(p);}static voidpooldumparena(Pool *p, Arena *a){	Bhdr *b;	for(b=a; b->magic != ARENATAIL_MAGIC; b=B2NB(b))		p->print(p, "(%p %.8lux %lud)", b, b->magic, b->size);	p->print(p, "\n");}/* * mark the memory in such a way that we know who marked it * (via the signature) and we know where the marking started. */static voidmemmark(void *v, int sig, ulong size){	uchar *p, *ep;	ulong *lp, *elp;	lp = v;	elp = lp+size/4;	while(lp < elp)		*lp++ = (sig<<24) ^ ((uintptr)lp-(uintptr)v);	p = (uchar*)lp;	ep = (uchar*)v+size;	while(p<ep)		*p++ = sig;}

⌨️ 快捷键说明

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