#include "go-string.h"
#include "interface.h"
#include "go-type.h"
-typedef struct __go_empty_interface Eface;
-typedef struct __go_type_descriptor Type;
-typedef struct __go_func_type FuncType;
MHeap runtime_mheap;
+
extern MStats mstats; // defined in extern.go
extern volatile int32 runtime_MemProfileRate
void*
runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
{
+ M *m;
+ G *g;
int32 sizeclass, rate;
MCache *c;
uintptr npages;
MSpan *s;
void *v;
- if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
+ m = runtime_m();
+ g = runtime_g();
+ if(g->status == Gsyscall)
+ dogc = 0;
+ if(runtime_gcwaiting && g != m->g0 && m->locks == 0 && g->status != Gsyscall) {
+ runtime_gosched();
+ m = runtime_m();
+ }
+ if(m->mallocing)
runtime_throw("malloc/free - deadlock");
+ m->mallocing = 1;
if(size == 0)
size = 1;
if(!(flag & FlagNoGC))
runtime_markallocated(v, size, (flag&FlagNoPointers) != 0);
- __sync_bool_compare_and_swap(&m->mallocing, 1, 0);
-
- if(__sync_bool_compare_and_swap(&m->gcing, 1, 0)) {
- if(!(flag & FlagNoProfiling))
- __go_run_goroutine_gc(0);
- else {
- // We are being called from the profiler. Tell it
- // to invoke the garbage collector when it is
- // done. No need to use a sync function here.
- m->gcing_for_prof = 1;
- }
- }
+ m->mallocing = 0;
if(!(flag & FlagNoProfiling) && (rate = runtime_MemProfileRate) > 0) {
if(size >= (uint32) rate)
void
__go_free(void *v)
{
+ M *m;
int32 sizeclass;
MSpan *s;
MCache *c;
if(v == nil)
return;
- // If you change this also change mgc0.c:/^sweepspan,
+ // If you change this also change mgc0.c:/^sweep,
// which has a copy of the guts of free.
- if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
+ m = runtime_m();
+ if(m->mallocing)
runtime_throw("malloc/free - deadlock");
+ m->mallocing = 1;
if(!runtime_mlookup(v, nil, nil, &s)) {
// runtime_printf("free %p: not an allocated block\n", v);
c->local_alloc -= size;
if(prof)
runtime_MProf_Free(v, size);
-
- __sync_bool_compare_and_swap(&m->mallocing, 1, 0);
-
- if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
- __go_run_goroutine_gc(1);
+ m->mallocing = 0;
}
int32
byte *p;
MSpan *s;
- m->mcache->local_nlookup++;
+ runtime_m()->mcache->local_nlookup++;
s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
if(sp)
*sp = s;
int32 rate;
MCache *c;
- if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
- runtime_throw("allocmcache - deadlock");
-
runtime_lock(&runtime_mheap);
c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
-
- // Clear the free list used by FixAlloc; assume the rest is zeroed.
- c->list[0].list = nil;
-
mstats.mcache_inuse = runtime_mheap.cachealloc.inuse;
mstats.mcache_sys = runtime_mheap.cachealloc.sys;
runtime_unlock(&runtime_mheap);
if(rate != 0)
c->next_sample = runtime_fastrand1() % (2*rate);
- __sync_bool_compare_and_swap(&m->mallocing, 1, 0);
- if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
- __go_run_goroutine_gc(2);
-
return c;
}
uintptr arena_size, bitmap_size;
extern byte end[];
byte *want;
+ uintptr limit;
runtime_sizeof_C_MStats = sizeof(MStats);
+ p = nil;
+ arena_size = 0;
+ bitmap_size = 0;
+
+ // for 64-bit build
+ USED(p);
+ USED(arena_size);
+ USED(bitmap_size);
+
runtime_InitSizes();
+ limit = runtime_memlimit();
+
// Set up the allocation arena, a contiguous area of memory where
// allocated data will be found. The arena begins with a bitmap large
// enough to hold 4 bits per allocated word.
- if(sizeof(void*) == 8) {
+ if(sizeof(void*) == 8 && (limit == 0 || limit > (1<<30))) {
// On a 64-bit machine, allocate from a single contiguous reservation.
// 16 GB should be big enough for now.
//
// Actually we reserve 17 GB (because the bitmap ends up being 1 GB)
// but it hardly matters: fc is not valid UTF-8 either, and we have to
// allocate 15 GB before we get that far.
+ //
+ // If this fails we fall back to the 32 bit memory mechanism
arena_size = (uintptr)(16LL<<30);
bitmap_size = arena_size / (sizeof(void*)*8/4);
p = runtime_SysReserve((void*)(0x00f8ULL<<32), bitmap_size + arena_size);
- if(p == nil)
- runtime_throw("runtime: cannot reserve arena virtual address space");
- } else {
+ }
+ if (p == nil) {
// On a 32-bit machine, we can't typically get away
// with a giant virtual address space reservation.
// Instead we map the memory information bitmap
// of address space, which is probably too much in a 32-bit world.
bitmap_size = MaxArena32 / (sizeof(void*)*8/4);
arena_size = 512<<20;
+ if(limit > 0 && arena_size+bitmap_size > limit) {
+ bitmap_size = (limit / 9) & ~((1<<PageShift) - 1);
+ arena_size = bitmap_size * 8;
+ }
// SysReserve treats the address we ask for, end, as a hint,
// not as an absolute requirement. If we ask for the end
p = runtime_SysReserve(want, bitmap_size + arena_size);
if(p == nil)
runtime_throw("runtime: cannot reserve arena virtual address space");
+ if((uintptr)p & (((uintptr)1<<PageShift)-1))
+ runtime_printf("runtime: SysReserve returned unaligned address %p; asked for %p", p, (void*)(bitmap_size+arena_size));
}
if((uintptr)p & (((uintptr)1<<PageShift)-1))
runtime_throw("runtime: SysReserve returned unaligned address");
// Initialize the rest of the allocator.
runtime_MHeap_Init(&runtime_mheap, runtime_SysAlloc);
- m->mcache = runtime_allocmcache();
+ runtime_m()->mcache = runtime_allocmcache();
// See if it works.
runtime_free(runtime_malloc(1));
{
byte *p;
+
+ if(n > (uintptr)(h->arena_end - h->arena_used)) {
+ // We are in 32-bit mode, maybe we didn't use all possible address space yet.
+ // Reserve some more space.
+ byte *new_end;
+ uintptr needed;
+
+ needed = (uintptr)h->arena_used + n - (uintptr)h->arena_end;
+ // Round wanted arena size to a multiple of 256MB.
+ needed = (needed + (256<<20) - 1) & ~((256<<20)-1);
+ new_end = h->arena_end + needed;
+ if(new_end <= h->arena_start + MaxArena32) {
+ p = runtime_SysReserve(h->arena_end, new_end - h->arena_end);
+ if(p == h->arena_end)
+ h->arena_end = new_end;
+ }
+ }
if(n <= (uintptr)(h->arena_end - h->arena_used)) {
// Keep taking from our reservation.
p = h->arena_used;
return p;
}
- // On 64-bit, our reservation is all we have.
- if(sizeof(void*) == 8)
+ // If using 64-bit, our reservation is all we have.
+ if(sizeof(void*) == 8 && (uintptr)h->bitmap >= 0xffffffffU)
return nil;
// On 32-bit, once the reservation is gone we can
return nil;
if(p < h->arena_start || (uintptr)(p+n - h->arena_start) >= MaxArena32) {
- runtime_printf("runtime: memory allocated by OS not in usable range\n");
+ runtime_printf("runtime: memory allocated by OS (%p) not in usable range [%p,%p)\n",
+ p, h->arena_start, h->arena_start+MaxArena32);
runtime_SysFree(p, n);
return nil;
}
ret = runtime_mallocgc(typ->__size, flag, 1, 1);
}
-func Alloc(n uintptr) (p *byte) {
- p = runtime_malloc(n);
-}
-
-func Free(p *byte) {
- runtime_free(p);
-}
-
-func Lookup(p *byte) (base *byte, size uintptr) {
- runtime_mlookup(p, &base, &size, nil);
-}
-
func GC() {
runtime_gc(1);
}