OSDN Git Service

runtime: Ignore stack sizes when deciding when to GC.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / malloc.goc
index abf020d..253fdbe 100644 (file)
@@ -17,11 +17,9 @@ package runtime
 #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
@@ -33,14 +31,25 @@ 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;
 
@@ -77,18 +86,7 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
        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)
@@ -122,6 +120,7 @@ __go_alloc(uintptr size)
 void
 __go_free(void *v)
 {
+       M *m;
        int32 sizeclass;
        MSpan *s;
        MCache *c;
@@ -131,11 +130,13 @@ __go_free(void *v)
        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);
@@ -170,11 +171,7 @@ __go_free(void *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
@@ -184,7 +181,7 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
        byte *p;
        MSpan *s;
 
-       m->mcache->local_nlookup++;
+       runtime_m()->mcache->local_nlookup++;
        s = runtime_MHeap_LookupMaybe(&runtime_mheap, v);
        if(sp)
                *sp = s;
@@ -229,15 +226,8 @@ runtime_allocmcache(void)
        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);
@@ -249,10 +239,6 @@ runtime_allocmcache(void)
        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;
 }
 
@@ -291,15 +277,27 @@ runtime_mallocinit(void)
        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.
                //
@@ -322,12 +320,13 @@ runtime_mallocinit(void)
                // 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
@@ -347,6 +346,10 @@ runtime_mallocinit(void)
                // 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
@@ -363,6 +366,8 @@ runtime_mallocinit(void)
                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");
@@ -374,7 +379,7 @@ runtime_mallocinit(void)
 
        // 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));
@@ -385,6 +390,23 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
 {
        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;
@@ -394,8 +416,8 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
                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
@@ -406,7 +428,8 @@ runtime_MHeap_SysAlloc(MHeap *h, uintptr n)
                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;
        }
@@ -434,18 +457,6 @@ func new(typ *Type) (ret *uint8) {
        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);
 }