This patch to libgo ignores space allocated for goroutine stacks when deciding when to next run the garbage collector. On systems that support split stacks this does nothing, as on those systems the stacks are allocated by the split stack code. On systems that do not support split stacks this doesn't let the large amount of memory allocated for stacks cause the system to delay GC unreasonably.
This patch also does a couple of other minor things. The heap bitmap bits are allocated in page size units. This fixes a problem on PPC GNU/Linux which uses a larger page size than x86. Also this clears the ucontext_t field in the G structure when it is put on the free list. This prevents the GC from thinking that old register values, now meaningless, are valid pointers requiring data to be kept in memory. Bootstrapped on x86_64-unknown-linux-gnu and powerpc64-unknown-linux-gnu. Committed to mainline and 4.7 branch. Ian
diff -r c8d973732b42 libgo/runtime/malloc.goc --- a/libgo/runtime/malloc.goc Thu Apr 19 21:46:43 2012 -0700 +++ b/libgo/runtime/malloc.goc Thu Apr 19 21:50:27 2012 -0700 @@ -72,7 +72,7 @@ npages = size >> PageShift; if((size & PageMask) != 0) npages++; - s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, !(flag & FlagNoGC)); + s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1); if(s == nil) runtime_throw("out of memory"); size = npages<<PageShift; diff -r c8d973732b42 libgo/runtime/mgc0.c --- a/libgo/runtime/mgc0.c Thu Apr 19 21:46:43 2012 -0700 +++ b/libgo/runtime/mgc0.c Thu Apr 19 21:50:27 2012 -0700 @@ -4,6 +4,8 @@ // Garbage collector. +#include <unistd.h> + #include "runtime.h" #include "arch.h" #include "malloc.h" @@ -918,7 +920,7 @@ uint64 stacks_sys; stacks_inuse = 0; - stacks_sys = 0; + stacks_sys = runtime_stacks_sys; for(m=runtime_allm; m; m=m->alllink) { runtime_purgecachedstats(m); // stacks_inuse += m->stackalloc->inuse; @@ -1020,7 +1022,7 @@ stealcache(); cachestats(); - mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100; + mstats.next_gc = mstats.heap_alloc+(mstats.heap_alloc-runtime_stacks_sys)*gcpercent/100; m->gcing = 0; m->locks++; // disable gc during the mallocs in newproc @@ -1329,6 +1331,8 @@ void runtime_MHeap_MapBits(MHeap *h) { + size_t page_size; + // Caller has added extra mappings to the arena. // Add extra mappings of bitmap words as needed. // We allocate extra bitmap pieces in chunks of bitmapChunk. @@ -1342,6 +1346,9 @@ if(h->bitmap_mapped >= n) return; + page_size = getpagesize(); + n = (n+page_size-1) & ~(page_size-1); + runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped); h->bitmap_mapped = n; } diff -r c8d973732b42 libgo/runtime/proc.c --- a/libgo/runtime/proc.c Thu Apr 19 21:46:43 2012 -0700 +++ b/libgo/runtime/proc.c Thu Apr 19 21:50:27 2012 -0700 @@ -46,6 +46,8 @@ # define StackMin 2 * 1024 * 1024 #endif +uintptr runtime_stacks_sys; + static void schedule(G*); typedef struct Sched Sched; @@ -1091,6 +1093,7 @@ m->lockedg = nil; } gp->idlem = nil; + runtime_memclr(&gp->context, sizeof gp->context); gfput(gp); if(--runtime_sched.gcount == 0) runtime_exit(0); @@ -1288,6 +1291,7 @@ *ret_stacksize = stacksize; newg->gcinitial_sp = *ret_stack; newg->gcstack_size = stacksize; + runtime_xadd(&runtime_stacks_sys, stacksize); #endif } return newg; diff -r c8d973732b42 libgo/runtime/runtime.h --- a/libgo/runtime/runtime.h Thu Apr 19 21:46:43 2012 -0700 +++ b/libgo/runtime/runtime.h Thu Apr 19 21:50:27 2012 -0700 @@ -463,3 +463,8 @@ }; void __go_register_gc_roots(struct root_list*); + +// Size of stack space allocated using Go's allocator. +// This will be 0 when using split stacks, as in that case +// the stacks are allocated by the splitstack library. +extern uintptr runtime_stacks_sys;