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

📄 malloc.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
字号:
#include <u.h>#include <libc.h>#include <pool.h>static void*	sbrkalloc(ulong);static int		sbrkmerge(void*, void*);static void		plock(Pool*);static void		punlock(Pool*);static void		pprint(Pool*, char*, ...);static void		ppanic(Pool*, char*, ...);typedef struct Private Private;struct Private {	Lock		lk;	int		printfd;	/* gets debugging output if set */};Private sbrkmempriv;static Pool sbrkmem = {	.name=		"sbrkmem",	.maxsize=		2*1024*1024*1024,	.minarena=	4*1024,	.quantum=	32,	.alloc=		sbrkalloc,	.merge=		sbrkmerge,	.flags=		0,	.lock=		plock,	.unlock=		punlock,	.print=		pprint,	.panic=		ppanic,	.private=		&sbrkmempriv,};Pool *mainmem = &sbrkmem;Pool *imagmem = &sbrkmem;/* * we do minimal bookkeeping so we can tell pool * whether two blocks are adjacent and thus mergeable. */static void*sbrkalloc(ulong n){	long *x;	n += 8;	/* two longs for us */	x = sbrk(n);	if((int)x == -1)		x = nil;	x[0] = (n+7)&~7;	/* sbrk rounds size up to mult. of 8 */	x[1] = 0xDeadBeef;	return x+2;}static intsbrkmerge(void *x, void *y){	long *lx, *ly;	lx = x;	if(lx[-1] != 0xDeadBeef)		abort();	if((uchar*)lx+lx[-2] == (uchar*)y) {		ly = y;		lx[-2] += ly[-2];		return 1;	}	return 0;}static voidplock(Pool *p){	Private *pv;	pv = p->private;	lock(&pv->lk);}static voidpunlock(Pool *p){	Private *pv;	pv = p->private;	unlock(&pv->lk);}static intcheckenv(void){	int n, fd;	char buf[20];	fd = open("/env/MALLOCFD", OREAD);	if(fd < 0)		return -1;	if((n = read(fd, buf, sizeof buf)) < 0) {		close(fd);		return -1;	}	if(n >= sizeof buf)		n = sizeof(buf)-1;	buf[n] = 0;	n = atoi(buf);	if(n == 0)		n = -1;	return n;}static voidpprint(Pool *p, char *fmt, ...){	va_list v;	int n;	char buf[128];	char *msg;	Private *pv;	pv = p->private;	if(pv->printfd == 0)		pv->printfd = checkenv();	if(pv->printfd <= 0)		pv->printfd = 2;	msg = buf;	va_start(v, fmt);	n = doprint(buf, buf+sizeof buf, fmt, v)-msg;	write(pv->printfd, buf, n);	va_end(v);}static char panicbuf[256];static voidppanic(Pool *p, char *fmt, ...) {	va_list v;	int n;	char *msg;	Private *pv;	pv = p->private;	assert(canlock(&pv->lk)==0);	if(pv->printfd == 0)		pv->printfd = checkenv();	if(pv->printfd <= 0)		pv->printfd = 2;	msg = panicbuf;	va_start(v, fmt);	n = doprint(msg, msg+sizeof panicbuf, fmt, v) - msg;	write(2, "panic: ", 7);	write(2, msg, n);	write(2, "\n", 1);	if(pv->printfd != 2){		write(pv->printfd, "panic: ", 7);		write(pv->printfd, msg, n);		write(pv->printfd, "\n", 1);	}	va_end(v);	unlock(&pv->lk);	abort();}/* - everything from here down should be the same in libc, libdebugmalloc, and the kernel - *//* - except the code for malloc(), which alternately doesn't clear or does. - *//* * Npadlong is the number of 32-bit longs to leave at the beginning of  * each allocated buffer for our own bookkeeping.  We return to the callers * a pointer that points immediately after our bookkeeping area.  Incoming pointers * must be decremented by that much, and outgoing pointers incremented. * The malloc tag is stored at MallocOffset from the beginning of the block, * and the realloc tag at ReallocOffset.  The offsets are from the true beginning * of the block, not the beginning the caller sees. * * The extra if(Npadlong != 0) in various places is a hint for the compiler to * compile out function calls that would otherwise be no-ops. *//*	non tracing *enum {	Npadlong	= 0,	MallocOffset = 0,	ReallocOffset = 0,}; * *//* tracing */enum {	Npadlong	= 2,	MallocOffset = 0,	ReallocOffset = 1};void*malloc(ulong size){	void *v;	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));	if(Npadlong && v != nil) {		v = (ulong*)v+Npadlong;		setmalloctag(v, getcallerpc(&size));		setrealloctag(v, 0);	}	return v;}void*mallocz(ulong size, int clr){	void *v;	v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));	if(Npadlong && v != nil){		v = (ulong*)v+Npadlong;		setmalloctag(v, getcallerpc(&size));		setrealloctag(v, 0);	}	if(clr && v != nil)		memset(v, 0, size);	return v;}voidfree(void *v){	if(v != nil)		poolfree(mainmem, (ulong*)v-Npadlong);}void*realloc(void *v, ulong size){	void *nv;	if(v == nil)		return malloc(size);	if(size == 0){		free(v);		return nil;	}	v = (ulong*)v-Npadlong;	size += Npadlong*sizeof(ulong);	if(nv = poolrealloc(mainmem, v, size)){		nv = (ulong*)nv+Npadlong;		setrealloctag(nv, getcallerpc(&v));		if(v == nil)			setmalloctag(nv, getcallerpc(&v));	}			return nv;}ulongmsize(void *v){	return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong);}void*calloc(ulong n, ulong szelem){	void *v;	if(v = mallocz(n*szelem, 1))		setmalloctag(v, getcallerpc(&n));	return v;}voidsetmalloctag(void *v, ulong pc){	ulong *u;	USED(v, pc);	if(Npadlong <= MallocOffset || v == nil)		return;	u = v;	u[-Npadlong+MallocOffset] = pc;}voidsetrealloctag(void *v, ulong pc){	ulong *u;	USED(v, pc);	if(Npadlong <= ReallocOffset || v == nil)		return;	u = v;	u[-Npadlong+ReallocOffset] = pc;}ulonggetmalloctag(void *v){	USED(v);	if(Npadlong <= MallocOffset)		return ~0;	return ((ulong*)v)[-Npadlong+MallocOffset];}ulonggetrealloctag(void *v){	USED(v);	if(Npadlong <= ReallocOffset)		return ((ulong*)v)[-Npadlong+ReallocOffset];	return ~0;}void*malloctopoolblock(void *v){	if(v == nil)		return nil;	return &((ulong*)v)[-Npadlong];}

⌨️ 快捷键说明

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