aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime/mheap.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-03-02 20:01:37 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-03-02 20:01:37 +0000
commit501699af1603287b1b47ac450fd6eeb826aa76b1 (patch)
tree3eeb8918d39d675108073c8b76d6dd10586a608c /libgo/runtime/mheap.c
parent34c5f21a387dc461042bafc3052ce6e1af786a77 (diff)
downloadgcc-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.c88
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(&note);
+ runtime_entersyscall();
+ runtime_notetsleep(&note, 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.