📄 malloc.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 + -