Commit c1868bc8 authored by Russ Cox's avatar Russ Cox

malloc fixes.

can run peano 10 in 100 MB (instead of 1+ GB) of memory
when linking against this.
can run peano 11 in 1 GB of memory now.

R=r
DELTA=100  (44 added, 44 deleted, 12 changed)
OCL=20504
CL=20553
parent 0d1cbaf2
...@@ -31,3 +31,7 @@ test%: test%.$O $(OFILES) ...@@ -31,3 +31,7 @@ test%: test%.$O $(OFILES)
clean: clean:
rm -f *.$O $(TARG) rm -f *.$O $(TARG)
runtime: allocator.$O malloc.$O pagemap.$O triv.$O stack.$O
6ar grc $(GOROOT)/lib/lib_$(GOARCH)_$(GOOS).a $^
...@@ -10,3 +10,4 @@ export func memset(*byte, int, int) ...@@ -10,3 +10,4 @@ export func memset(*byte, int, int)
export var footprint int64 export var footprint int64
export var frozen bool export var frozen bool
export func testsizetoclass() export func testsizetoclass()
export var allocated int64
...@@ -107,13 +107,7 @@ allocspan(int32 npage) ...@@ -107,13 +107,7 @@ allocspan(int32 npage)
if(s->length >= npage) { if(s->length >= npage) {
*l = s->next; *l = s->next;
s->next = nil; s->next = nil;
if(s->length > npage) { //if(s->length > npage) printf("Chop span %D for %d\n", s->length, npage);
prints("Chop span");
sys·printint(s->length);
prints(" for ");
sys·printint(npage);
prints("\n");
}
goto havespan; goto havespan;
} }
} }
...@@ -125,11 +119,7 @@ prints("\n"); ...@@ -125,11 +119,7 @@ prints("\n");
if(allocnpage < (1<<20>>PageShift)) // TODO: Tune if(allocnpage < (1<<20>>PageShift)) // TODO: Tune
allocnpage = (1<<20>>PageShift); allocnpage = (1<<20>>PageShift);
s->length = allocnpage; s->length = allocnpage;
prints("New span "); //printf("New span %d for %d\n", allocnpage, npage);
sys·printint(allocnpage);
prints(" for ");
sys·printint(npage);
prints("\n");
s->base = trivalloc(allocnpage<<PageShift); s->base = trivalloc(allocnpage<<PageShift);
insertspan(s); insertspan(s);
...@@ -237,21 +227,13 @@ allocator·testsizetoclass(void) ...@@ -237,21 +227,13 @@ allocator·testsizetoclass(void)
for(i=0; i<nelem(classtosize); i++) { for(i=0; i<nelem(classtosize); i++) {
for(; n <= classtosize[i]; n++) { for(; n <= classtosize[i]; n++) {
if(sizetoclass(n) != i) { if(sizetoclass(n) != i) {
prints("sizetoclass "); printf("sizetoclass %d = %d want %d\n", n, sizetoclass(n), i);
sys·printint(n);
prints(" = ");
sys·printint(sizetoclass(n));
prints(" want ");
sys·printint(i);
prints("\n");
throw("testsizetoclass"); throw("testsizetoclass");
} }
} }
} }
if (n != 32768+1) { if (n != 32768+1) {
prints("testsizetoclass stopped at "); printf("testsizetoclass stopped at %d\n", n);
sys·printint(n);
prints("\n");
throw("testsizetoclass"); throw("testsizetoclass");
} }
} }
...@@ -274,20 +256,19 @@ centralgrab(int32 cl, int32 *pn) ...@@ -274,20 +256,19 @@ centralgrab(int32 cl, int32 *pn)
} }
chunk = (chunk+PageMask) & ~PageMask; chunk = (chunk+PageMask) & ~PageMask;
s = allocspan(chunk>>PageShift); s = allocspan(chunk>>PageShift);
prints("New Class "); //printf("New class %d\n", cl);
sys·printint(cl);
prints("\n");
s->state = SpanInUse; s->state = SpanInUse;
s->cl = cl; s->cl = cl;
siz = classtosize[cl]; siz = classtosize[cl];
n = chunk/siz; n = chunk/siz;
p = s->base; p = s->base;
//printf("centralgrab cl=%d siz=%d n=%d\n", cl, siz, n);
for(i=0; i<n-1; i++) { for(i=0; i<n-1; i++) {
*(void**)p = p+siz; *(void**)p = p+siz;
p += siz; p += siz;
} }
*pn = n; *pn = n;
return p; return s->base;
} }
// Allocate a small object of size class cl. // Allocate a small object of size class cl.
...@@ -305,11 +286,13 @@ allocsmall(int32 cl) ...@@ -305,11 +286,13 @@ allocsmall(int32 cl)
if(p == nil) { if(p == nil) {
// otherwise grab some blocks from central cache. // otherwise grab some blocks from central cache.
lock(&central); lock(&central);
//printf("centralgrab for %d\n", cl);
p = centralgrab(cl, &n); p = centralgrab(cl, &n);
// TODO: update local counters using n // TODO: update local counters using n
unlock(&central); unlock(&central);
} }
//printf("alloc from cl %d\n", cl);
// advance linked list. // advance linked list.
m->freelist[cl] = *p; m->freelist[cl] = *p;
...@@ -327,9 +310,7 @@ alloclarge(int32 np) ...@@ -327,9 +310,7 @@ alloclarge(int32 np)
Span *s; Span *s;
lock(&central); lock(&central);
//prints("Alloc span "); //printf("Alloc span %d\n", np);
//sys·printint(np);
//prints("\n");
s = allocspan(np); s = allocspan(np);
unlock(&central); unlock(&central);
s->state = SpanInUse; s->state = SpanInUse;
...@@ -346,17 +327,16 @@ alloc(int32 n) ...@@ -346,17 +327,16 @@ alloc(int32 n)
if(n < LargeSize) { if(n < LargeSize) {
cl = sizetoclass(n); cl = sizetoclass(n);
if(cl < 0 || cl >= SmallFreeClasses) { if(cl < 0 || cl >= SmallFreeClasses) {
sys·printint(n); printf("%d -> %d\n", n, cl);
prints(" -> ");
sys·printint(cl);
prints("\n");
throw("alloc - logic error"); throw("alloc - logic error");
} }
return allocsmall(sizetoclass(n)); allocator·allocated += classtosize[cl];
return allocsmall(cl);
} }
// count number of pages; careful about overflow for big n. // count number of pages; careful about overflow for big n.
np = (n>>PageShift) + (((n&PageMask)+PageMask)>>PageShift); np = (n>>PageShift) + (((n&PageMask)+PageMask)>>PageShift);
allocator·allocated += (uint64)np<<PageShift;
return alloclarge(np); return alloclarge(np);
} }
...@@ -386,9 +366,8 @@ free(void *v) ...@@ -386,9 +366,8 @@ free(void *v)
// TODO: For large spans, maybe just return the // TODO: For large spans, maybe just return the
// memory to the operating system and let it zero it. // memory to the operating system and let it zero it.
sys·memclr(s->base, s->length << PageShift); sys·memclr(s->base, s->length << PageShift);
//prints("Free big "); //printf("Free big %D\n", s->length);
//sys·printint(s->length); allocator·allocated -= s->length << PageShift;
//prints("\n");
lock(&central); lock(&central);
freespan(s); freespan(s);
unlock(&central); unlock(&central);
...@@ -403,9 +382,11 @@ free(void *v) ...@@ -403,9 +382,11 @@ free(void *v)
// Zero and add to free list. // Zero and add to free list.
sys·memclr(v, siz); sys·memclr(v, siz);
allocator·allocated -= siz;
p = v; p = v;
*p = m->freelist[s->cl]; *p = m->freelist[s->cl];
m->freelist[s->cl] = p; m->freelist[s->cl] = p;
//printf("Free siz %d cl %d\n", siz, s->cl);
} }
void void
...@@ -423,21 +404,3 @@ allocator·memset(byte *v, int32 c, int32 n) ...@@ -423,21 +404,3 @@ allocator·memset(byte *v, int32 c, int32 n)
v[i] = c; v[i] = c;
} }
// Allocate stack segment.
// Must be done without holding locks, because
// calling any function might trigger another stack segment allocation.
void*
allocstack(int32 n)
{
// TODO
USED(n);
return nil;
}
void
freestack(void *v)
{
// TODO
USED(v);
}
...@@ -24,9 +24,13 @@ struct PageMap ...@@ -24,9 +24,13 @@ struct PageMap
void *level0[PMLevelSize]; void *level0[PMLevelSize];
}; };
extern int64 allocator·allocated;
extern int64 allocator·footprint; extern int64 allocator·footprint;
extern bool allocator·frozen; extern bool allocator·frozen;
void* trivalloc(int32); void* trivalloc(int32);
void* pmlookup(PageMap*, uintptr); void* pmlookup(PageMap*, uintptr);
void* pminsert(PageMap*, uintptr, void*); void* pminsert(PageMap*, uintptr, void*);
void* alloc(int32);
void free(void*);
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "malloc.h"
void*
stackalloc(uint32 n)
{
void *v;
v = alloc(n);
//printf("stackalloc %d = %p\n", n, v);
return v;
}
void
stackfree(void *v)
{
//printf("stackfree %p\n", v);
free(v);
}
...@@ -36,6 +36,7 @@ trivalloc(int32 size) ...@@ -36,6 +36,7 @@ trivalloc(int32 size)
static byte *p; static byte *p;
static int32 n; static int32 n;
byte *v; byte *v;
uint64 oldfoot;
if(allocator·frozen) if(allocator·frozen)
throw("allocator frozen"); throw("allocator frozen");
...@@ -44,6 +45,7 @@ trivalloc(int32 size) ...@@ -44,6 +45,7 @@ trivalloc(int32 size)
//sys·printint(size); //sys·printint(size);
//prints("\n"); //prints("\n");
oldfoot = allocator·footprint;
if(size < 4096) { // TODO: Tune constant. if(size < 4096) { // TODO: Tune constant.
size = (size + Round) & ~Round; size = (size + Round) & ~Round;
if(size > n) { if(size > n) {
...@@ -53,12 +55,20 @@ trivalloc(int32 size) ...@@ -53,12 +55,20 @@ trivalloc(int32 size)
} }
v = p; v = p;
p += size; p += size;
return v; goto out;
} }
if(size & PageMask) if(size & PageMask)
size += (1<<PageShift) - (size & PageMask); size += (1<<PageShift) - (size & PageMask);
v = sys·mmap(nil, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); v = sys·mmap(nil, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0);
allocator·footprint += size; allocator·footprint += size;
out:
if((oldfoot>>24) != (allocator·footprint>>24))
printf("memory footprint = %D MB for %D MB\n", allocator·footprint>>20, allocator·allocated>>20);
if(allocator·footprint >= 2LL<<30) {
prints("out of memory\n");
sys·exit(1);
}
return v; return v;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment