aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime/malloc.goc
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/runtime/malloc.goc')
-rw-r--r--libgo/runtime/malloc.goc114
1 files changed, 81 insertions, 33 deletions
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index a484642..dfab683 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -18,7 +18,7 @@ package runtime
#include "go-type.h"
#include "race.h"
-MHeap runtime_mheap;
+MHeap *runtime_mheap;
int32 runtime_checking;
@@ -46,7 +46,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
g = runtime_g();
if(g->status == Gsyscall)
dogc = 0;
- if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && g->status != Gsyscall) {
+ if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && dogc) {
runtime_gosched();
m = runtime_m();
}
@@ -78,7 +78,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
npages = size >> PageShift;
if((size & PageMask) != 0)
npages++;
- s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, zeroed);
+ s = runtime_MHeap_Alloc(runtime_mheap, npages, 0, 1, zeroed);
if(s == nil)
runtime_throw("out of memory");
size = npages<<PageShift;
@@ -92,9 +92,9 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
if (sizeof(void*) == 4 && c->local_total_alloc >= (1<<30)) {
// purge cache stats to prevent overflow
- runtime_lock(&runtime_mheap);
+ runtime_lock(runtime_mheap);
runtime_purgecachedstats(c);
- runtime_unlock(&runtime_mheap);
+ runtime_unlock(runtime_mheap);
}
if(!(flag & FlagNoGC))
@@ -175,17 +175,17 @@ __go_free(void *v)
if(sizeclass == 0) {
// Large object.
size = s->npages<<PageShift;
- *(uintptr*)(s->start<<PageShift) = 1; // mark as "needs to be zeroed"
+ *(uintptr*)(s->start<<PageShift) = (uintptr)0xfeedfeedfeedfeedll; // mark as "needs to be zeroed"
// Must mark v freed before calling unmarkspan and MHeap_Free:
// they might coalesce v into other spans and change the bitmap further.
runtime_markfreed(v, size);
runtime_unmarkspan(v, 1<<PageShift);
- runtime_MHeap_Free(&runtime_mheap, s, 1);
+ runtime_MHeap_Free(runtime_mheap, s, 1);
} else {
// Small object.
size = runtime_class_to_size[sizeclass];
if(size > sizeof(uintptr))
- ((uintptr*)v)[1] = 1; // mark as "needs to be zeroed"
+ ((uintptr*)v)[1] = (uintptr)0xfeedfeedfeedfeedll; // mark as "needs to be zeroed"
// Must mark v freed before calling MCache_Free:
// it might coalesce v and other blocks into a bigger span
// and change the bitmap further.
@@ -213,12 +213,12 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
m->mcache->local_nlookup++;
if (sizeof(void*) == 4 && m->mcache->local_nlookup >= (1<<30)) {
// purge cache stats to prevent overflow
- runtime_lock(&runtime_mheap);
+ runtime_lock(runtime_mheap);
runtime_purgecachedstats(m->mcache);
- runtime_unlock(&runtime_mheap);
+ runtime_unlock(runtime_mheap);
}
- s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
+ s = runtime_MHeap_LookupMaybe(runtime_mheap, v);
if(sp)
*sp = s;
if(s == nil) {
@@ -262,11 +262,11 @@ runtime_allocmcache(void)
intgo rate;
MCache *c;
- runtime_lock(&runtime_mheap);
- c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
- mstats.mcache_inuse = runtime_mheap.cachealloc.inuse;
- mstats.mcache_sys = runtime_mheap.cachealloc.sys;
- runtime_unlock(&runtime_mheap);
+ runtime_lock(runtime_mheap);
+ c = runtime_FixAlloc_Alloc(&runtime_mheap->cachealloc);
+ mstats.mcache_inuse = runtime_mheap->cachealloc.inuse;
+ mstats.mcache_sys = runtime_mheap->cachealloc.sys;
+ runtime_unlock(runtime_mheap);
runtime_memclr((byte*)c, sizeof(*c));
// Set first allocation sample size.
@@ -283,10 +283,10 @@ void
runtime_freemcache(MCache *c)
{
runtime_MCache_ReleaseAll(c);
- runtime_lock(&runtime_mheap);
+ runtime_lock(runtime_mheap);
runtime_purgecachedstats(c);
- runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c);
- runtime_unlock(&runtime_mheap);
+ runtime_FixAlloc_Free(&runtime_mheap->cachealloc, c);
+ runtime_unlock(runtime_mheap);
}
void
@@ -334,9 +334,15 @@ runtime_mallocinit(void)
USED(arena_size);
USED(bitmap_size);
+ if((runtime_mheap = runtime_SysAlloc(sizeof(*runtime_mheap))) == nil)
+ runtime_throw("runtime: cannot allocate heap metadata");
+
runtime_InitSizes();
- limit = runtime_memlimit();
+ // limit = runtime_memlimit();
+ // See https://code.google.com/p/go/issues/detail?id=5049
+ // TODO(rsc): Fix after 1.1.
+ limit = 0;
// Set up the allocation arena, a contiguous area of memory where
// allocated data will be found. The arena begins with a bitmap large
@@ -414,13 +420,13 @@ runtime_mallocinit(void)
if((uintptr)p & (((uintptr)1<<PageShift)-1))
runtime_throw("runtime: SysReserve returned unaligned address");
- runtime_mheap.bitmap = p;
- runtime_mheap.arena_start = p + bitmap_size;
- runtime_mheap.arena_used = runtime_mheap.arena_start;
- runtime_mheap.arena_end = runtime_mheap.arena_start + arena_size;
+ runtime_mheap->bitmap = p;
+ runtime_mheap->arena_start = p + bitmap_size;
+ runtime_mheap->arena_used = runtime_mheap->arena_start;
+ runtime_mheap->arena_end = runtime_mheap->arena_start + arena_size;
// Initialize the rest of the allocator.
- runtime_MHeap_Init(&runtime_mheap, runtime_SysAlloc);
+ runtime_MHeap_Init(runtime_mheap, runtime_SysAlloc);
runtime_m()->mcache = runtime_allocmcache();
// See if it works.
@@ -519,8 +525,8 @@ runtime_settype_flush(M *mp, bool sysalloc)
// (Manually inlined copy of runtime_MHeap_Lookup)
p = (uintptr)v>>PageShift;
if(sizeof(void*) == 8)
- p -= (uintptr)runtime_mheap.arena_start >> PageShift;
- s = runtime_mheap.map[p];
+ p -= (uintptr)runtime_mheap->arena_start >> PageShift;
+ s = runtime_mheap->map[p];
if(s->sizeclass == 0) {
s->types.compression = MTypes_Single;
@@ -537,9 +543,11 @@ runtime_settype_flush(M *mp, bool sysalloc)
nbytes3 = 8*sizeof(uintptr) + 1*ntypes;
if(!sysalloc) {
- data3 = runtime_mallocgc(nbytes3, FlagNoPointers, 0, 1);
+ data3 = runtime_mallocgc(nbytes3, FlagNoProfiling|FlagNoPointers, 0, 1);
} else {
data3 = runtime_SysAlloc(nbytes3);
+ if(data3 == nil)
+ runtime_throw("runtime: cannot allocate memory");
if(0) runtime_printf("settype(0->3): SysAlloc(%x) --> %p\n", (uint32)nbytes3, data3);
}
@@ -573,9 +581,11 @@ runtime_settype_flush(M *mp, bool sysalloc)
nbytes2 = ntypes * sizeof(uintptr);
if(!sysalloc) {
- data2 = runtime_mallocgc(nbytes2, FlagNoPointers, 0, 1);
+ data2 = runtime_mallocgc(nbytes2, FlagNoProfiling|FlagNoPointers, 0, 1);
} else {
data2 = runtime_SysAlloc(nbytes2);
+ if(data2 == nil)
+ runtime_throw("runtime: cannot allocate memory");
if(0) runtime_printf("settype.(3->2): SysAlloc(%x) --> %p\n", (uint32)nbytes2, data2);
}
@@ -633,7 +643,7 @@ runtime_settype(void *v, uintptr t)
}
if(DebugTypeAtBlockEnd) {
- s = runtime_MHeap_Lookup(&runtime_mheap, v);
+ s = runtime_MHeap_Lookup(runtime_mheap, v);
*(uintptr*)((uintptr)v+s->elemsize-sizeof(uintptr)) = t;
}
}
@@ -672,7 +682,7 @@ runtime_gettype(void *v)
uintptr t, ofs;
byte *data;
- s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
+ s = runtime_MHeap_LookupMaybe(runtime_mheap, v);
if(s != nil) {
t = 0;
switch(s->types.compression) {
@@ -731,9 +741,8 @@ runtime_new(const Type *typ)
ret = runtime_mallocgc(typ->__size, flag, 1, 1);
if(UseSpanType && !flag) {
- if(false) {
+ if(false)
runtime_printf("new %S: %p\n", *typ->__reflection, ret);
- }
runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject);
}
}
@@ -741,6 +750,45 @@ runtime_new(const Type *typ)
return ret;
}
+static void*
+cnew(const Type *typ, intgo n, int32 objtyp)
+{
+ uint32 flag;
+ void *ret;
+
+ if((objtyp&(PtrSize-1)) != objtyp)
+ runtime_throw("runtime: invalid objtyp");
+ if(n < 0 || (typ->__size > 0 && (uintptr)n > (MaxMem/typ->__size)))
+ runtime_panicstring("runtime: allocation size out of range");
+ if(typ->__size == 0 || n == 0) {
+ // All 0-length allocations use this pointer.
+ // The language does not require the allocations to
+ // have distinct values.
+ return &runtime_zerobase;
+ }
+ flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
+ ret = runtime_mallocgc(typ->__size*n, flag, 1, 1);
+ if(UseSpanType && !flag) {
+ if(false)
+ runtime_printf("cnew [%D]%S: %p\n", (int64)n, *typ->__reflection, ret);
+ runtime_settype(ret, (uintptr)typ | TypeInfo_SingleObject);
+ }
+ return ret;
+}
+
+// same as runtime_new, but callable from C
+void*
+runtime_cnew(const Type *typ)
+{
+ return cnew(typ, 1, TypeInfo_SingleObject);
+}
+
+void*
+runtime_cnewarray(const Type *typ, intgo n)
+{
+ return cnew(typ, n, TypeInfo_Array);
+}
+
func GC() {
runtime_gc(1);
}