diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-03-02 20:01:37 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-03-02 20:01:37 +0000 |
commit | 501699af1603287b1b47ac450fd6eeb826aa76b1 (patch) | |
tree | 3eeb8918d39d675108073c8b76d6dd10586a608c /libgo/runtime/mheap.c | |
parent | 34c5f21a387dc461042bafc3052ce6e1af786a77 (diff) | |
download | gcc-501699af1603287b1b47ac450fd6eeb826aa76b1.zip gcc-501699af1603287b1b47ac450fd6eeb826aa76b1.tar.gz gcc-501699af1603287b1b47ac450fd6eeb826aa76b1.tar.bz2 |
libgo: Update to weekly.2012-02-22 release.
From-SVN: r184819
Diffstat (limited to 'libgo/runtime/mheap.c')
-rw-r--r-- | libgo/runtime/mheap.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c index 5a5a1e7..79359d9 100644 --- a/libgo/runtime/mheap.c +++ b/libgo/runtime/mheap.c @@ -103,6 +103,8 @@ HaveSpan: runtime_MSpanList_Remove(s); s->state = MSpanInUse; mstats.heap_idle -= s->npages<<PageShift; + mstats.heap_released -= s->npreleased<<PageShift; + s->npreleased = 0; if(s->npages > npage) { // Trim extra and put it back in the heap. @@ -280,6 +282,8 @@ MHeap_FreeLocked(MHeap *h, MSpan *s) } mstats.heap_idle += s->npages<<PageShift; s->state = MSpanFree; + s->unusedsince = 0; + s->npreleased = 0; runtime_MSpanList_Remove(s); sp = (uintptr*)(s->start<<PageShift); @@ -292,6 +296,7 @@ MHeap_FreeLocked(MHeap *h, MSpan *s) *tp |= *sp; // propagate "needs zeroing" mark s->start = t->start; s->npages += t->npages; + s->npreleased = t->npreleased; // absorb released pages p -= t->npages; h->map[p] = s; runtime_MSpanList_Remove(t); @@ -304,6 +309,7 @@ MHeap_FreeLocked(MHeap *h, MSpan *s) tp = (uintptr*)(t->start<<PageShift); *sp |= *tp; // propagate "needs zeroing" mark s->npages += t->npages; + s->npreleased += t->npreleased; h->map[p + s->npages - 1] = s; runtime_MSpanList_Remove(t); t->state = MSpanDead; @@ -317,8 +323,86 @@ MHeap_FreeLocked(MHeap *h, MSpan *s) runtime_MSpanList_Insert(&h->free[s->npages], s); else runtime_MSpanList_Insert(&h->large, s); +} - // TODO(rsc): IncrementalScavenge() to return memory to OS. +// Release (part of) unused memory to OS. +// Goroutine created in runtime_schedinit. +// Loop forever. +void +runtime_MHeap_Scavenger(void* dummy) +{ + MHeap *h; + MSpan *s, *list; + uint64 tick, now, forcegc, limit; + uint32 k, i; + uintptr released, sumreleased; + const byte *env; + bool trace; + Note note; + + USED(dummy); + + // If we go two minutes without a garbage collection, force one to run. + forcegc = 2*60*1e9; + // If a span goes unused for 5 minutes after a garbage collection, + // we hand it back to the operating system. + limit = 5*60*1e9; + // Make wake-up period small enough for the sampling to be correct. + if(forcegc < limit) + tick = forcegc/2; + else + tick = limit/2; + + trace = false; + env = runtime_getenv("GOGCTRACE"); + if(env != nil) + trace = runtime_atoi(env) > 0; + + h = &runtime_mheap; + for(k=0;; k++) { + runtime_noteclear(¬e); + runtime_entersyscall(); + runtime_notetsleep(¬e, tick); + runtime_exitsyscall(); + + runtime_lock(h); + now = runtime_nanotime(); + if(now - mstats.last_gc > forcegc) { + runtime_unlock(h); + runtime_gc(1); + runtime_lock(h); + now = runtime_nanotime(); + if (trace) + runtime_printf("scvg%d: GC forced\n", k); + } + sumreleased = 0; + for(i=0; i < nelem(h->free)+1; i++) { + if(i < nelem(h->free)) + list = &h->free[i]; + else + list = &h->large; + if(runtime_MSpanList_IsEmpty(list)) + continue; + for(s=list->next; s != list; s=s->next) { + if(s->unusedsince != 0 && (now - s->unusedsince) > limit) { + released = (s->npages - s->npreleased) << PageShift; + mstats.heap_released += released; + sumreleased += released; + s->npreleased = s->npages; + runtime_SysUnused((void*)(s->start << PageShift), s->npages << PageShift); + } + } + } + runtime_unlock(h); + + if(trace) { + if(sumreleased > 0) + runtime_printf("scvg%d: %p MB released\n", k, (void*)(sumreleased>>20)); + runtime_printf("scvg%d: inuse: %lld, idle: %lld, sys: %lld, released: %lld, consumed: %lld (MB)\n", + k, (long long)(mstats.heap_inuse>>20), (long long)(mstats.heap_idle>>20), (long long)(mstats.heap_sys>>20), + (long long)(mstats.heap_released>>20), (long long)((mstats.heap_sys - mstats.heap_released)>>20)); + } + } } // Initialize a new span with the given start and npages. @@ -333,6 +417,8 @@ runtime_MSpan_Init(MSpan *span, PageID start, uintptr npages) span->ref = 0; span->sizeclass = 0; span->state = 0; + span->unusedsince = 0; + span->npreleased = 0; } // Initialize an empty doubly-linked list. |