diff options
| author | Russ Cox <rsc@golang.org> | 2008-12-19 03:13:39 -0800 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2008-12-19 03:13:39 -0800 |
| commit | da0a7d7b8f896bc2117ce488c4e245d626ef8aba (patch) | |
| tree | 9b40150f73466d543e7724ee596fb3c4ef094e72 /src/runtime/mcentral.c | |
| parent | ba882f9940361e7f9f969fcc1cc613e735d38191 (diff) | |
| download | go-da0a7d7b8f896bc2117ce488c4e245d626ef8aba.tar.xz | |
malloc bug fixes.
use malloc by default.
free stacks.
R=r
DELTA=424 (333 added, 29 deleted, 62 changed)
OCL=21553
CL=21584
Diffstat (limited to 'src/runtime/mcentral.c')
| -rw-r--r-- | src/runtime/mcentral.c | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/src/runtime/mcentral.c b/src/runtime/mcentral.c index 775ccb32d5..badf68eae2 100644 --- a/src/runtime/mcentral.c +++ b/src/runtime/mcentral.c @@ -35,42 +35,35 @@ MCentral_Init(MCentral *c, int32 sizeclass) // The objects are linked together by their first words. // On return, *pstart points at the first object and *pend at the last. int32 -MCentral_AllocList(MCentral *c, int32 n, void **pstart, void **pend) +MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst) { - void *start, *end, *v; + MLink *first, *last, *v; int32 i; - *pstart = nil; - *pend = nil; lock(c); - // Replenish central list if empty. if(MSpanList_IsEmpty(&c->nonempty)) { if(!MCentral_Grow(c)) { unlock(c); + *pfirst = nil; return 0; } } // Copy from list, up to n. - start = nil; - end = nil; - for(i=0; i<n; i++) { - v = MCentral_Alloc(c); - if(v == nil) - break; - if(start == nil) - start = v; - else - *(void**)end = v; - end = v; + // First one is guaranteed to work, because we just grew the list. + first = MCentral_Alloc(c); + last = first; + for(i=1; i<n && (v = MCentral_Alloc(c)) != nil; i++) { + last->next = v; + last = v; } + last->next = nil; c->nfree -= i; unlock(c); - *pstart = start; - *pend = end; + *pfirst = first; return i; } @@ -79,18 +72,18 @@ static void* MCentral_Alloc(MCentral *c) { MSpan *s; - void *v; + MLink *v; if(MSpanList_IsEmpty(&c->nonempty)) return nil; s = c->nonempty.next; + s->ref++; v = s->freelist; - s->freelist = *(void**)v; + s->freelist = v->next; if(s->freelist == nil) { MSpanList_Remove(s); MSpanList_Insert(&c->empty, s); } - s->ref++; return v; } @@ -99,19 +92,18 @@ MCentral_Alloc(MCentral *c) // The objects are linked together by their first words. // On return, *pstart points at the first object and *pend at the last. void -MCentral_FreeList(MCentral *c, int32 n, void *start, void *end) +MCentral_FreeList(MCentral *c, int32 n, void *start) { - void *v, *next; + MLink *v, *next; - // Assume *(void**)end = nil marks end of list. + // Assume next == nil marks end of list. // n and end would be useful if we implemented // the transfer cache optimization in the TODO above. USED(n); - USED(end); lock(c); for(v=start; v; v=next) { - next = *(void**)v; + next = v->next; MCentral_Free(c, v); } unlock(c); @@ -122,11 +114,12 @@ static void MCentral_Free(MCentral *c, void *v) { MSpan *s; - PageID p; + PageID page; + MLink *p, *next; // Find span for v. - p = (uintptr)v >> PageShift; - s = MHeap_Lookup(&mheap, p); + page = (uintptr)v >> PageShift; + s = MHeap_Lookup(&mheap, page); if(s == nil || s->ref == 0) throw("invalid free"); @@ -137,13 +130,21 @@ MCentral_Free(MCentral *c, void *v) } // Add v back to s's free list. - *(void**)v = s->freelist; - s->freelist = v; + p = v; + p->next = s->freelist; + s->freelist = p; c->nfree++; // If s is completely freed, return it to the heap. if(--s->ref == 0) { MSpanList_Remove(s); + // Freed blocks are zeroed except for the link pointer. + // Zero the link pointers so that the page is all zero. + for(p=s->freelist; p; p=next) { + next = p->next; + p->next = nil; + } + s->freelist = nil; c->nfree -= (s->npages << PageShift) / class_to_size[c->sizeclass]; unlock(c); MHeap_Free(&mheap, s); @@ -157,7 +158,7 @@ static bool MCentral_Grow(MCentral *c) { int32 n, npages, size; - void **tail; + MLink **tailp, *v; byte *p, *end; MSpan *s; @@ -171,17 +172,18 @@ MCentral_Grow(MCentral *c) } // Carve span into sequence of blocks. - tail = &s->freelist; + tailp = &s->freelist; p = (byte*)(s->start << PageShift); end = p + (npages << PageShift); size = class_to_size[c->sizeclass]; n = 0; for(; p + size <= end; p += size) { - *tail = p; - tail = (void**)p; + v = (MLink*)p; + *tailp = v; + tailp = &v->next; n++; } - *tail = nil; + *tailp = nil; lock(c); c->nfree += n; |
