aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2014-05-19 12:06:30 +0400
committerDmitriy Vyukov <dvyukov@google.com>2014-05-19 12:06:30 +0400
commite893acf1848b96a922356eb753e8cea79f469afd (patch)
tree4d2a7c0b6be80fbb053493cad8e70b9b2114d308
parentd021d982daa3f12701722bcb5420675fd2295d6a (diff)
downloadgo-e893acf1848b96a922356eb753e8cea79f469afd.tar.xz
runtime: fix freeOSMemory to free memory immediately
Currently freeOSMemory makes only marking phase of GC, but not sweeping phase. So recently memory is not released after freeOSMemory. Do both marking and sweeping during freeOSMemory. Fixes #8019. LGTM=khr R=golang-codereviews, khr CC=golang-codereviews, rsc https://golang.org/cl/97550043
-rw-r--r--src/pkg/runtime/malloc.goc11
-rw-r--r--src/pkg/runtime/mgc0.c8
-rw-r--r--src/pkg/runtime/mheap.c2
3 files changed, 8 insertions, 13 deletions
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index 6371689a9c..6e1068d93d 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -849,16 +849,7 @@ runtime·cnewarray(Type *typ, intgo n)
}
func GC() {
- // We assume that the user expects unused memory to have
- // been freed when GC returns. To ensure this, run gc(1) twice.
- // The first will do a collection, and the second will force the
- // first's sweeping to finish before doing a second collection.
- // The second collection is overkill, but we assume the user
- // has a good reason for calling runtime.GC and can stand the
- // expense. At the least, this fixes all the calls to runtime.GC in
- // tests that expect finalizers to start running when GC returns.
- runtime·gc(1);
- runtime·gc(1);
+ runtime·gc(2); // force GC and do eager sweep
}
func SetFinalizer(obj Eface, finalizer Eface) {
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index 7152e3b37c..e51ce24ff6 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -2239,6 +2239,7 @@ runtime·updatememstats(GCStats *stats)
struct gc_args
{
int64 start_time; // start time of GC in ns (just before stoptheworld)
+ bool eagersweep;
};
static void gc(struct gc_args *args);
@@ -2257,6 +2258,8 @@ readgogc(void)
return runtime·atoi(p);
}
+// force = 1 - do GC regardless of current heap usage
+// force = 2 - go GC and eager sweep
void
runtime·gc(int32 force)
{
@@ -2292,7 +2295,7 @@ runtime·gc(int32 force)
return;
runtime·semacquire(&runtime·worldsema, false);
- if(!force && mstats.heap_alloc < mstats.next_gc) {
+ if(force==0 && mstats.heap_alloc < mstats.next_gc) {
// typically threads which lost the race to grab
// worldsema exit here when gc is done.
runtime·semrelease(&runtime·worldsema);
@@ -2301,6 +2304,7 @@ runtime·gc(int32 force)
// Ok, we're doing it! Stop everybody else
a.start_time = runtime·nanotime();
+ a.eagersweep = force >= 2;
m->gcing = 1;
runtime·stoptheworld();
@@ -2490,7 +2494,7 @@ gc(struct gc_args *args)
sweep.spanidx = 0;
// Temporary disable concurrent sweep, because we see failures on builders.
- if(ConcurrentSweep) {
+ if(ConcurrentSweep && !args->eagersweep) {
runtime·lock(&gclock);
if(sweep.g == nil)
sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, runtime·gc);
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index 3de6b8bb4e..7e83eb2833 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -555,7 +555,7 @@ runtime·MHeap_Scavenger(void)
void
runtime∕debug·freeOSMemory(void)
{
- runtime·gc(1);
+ runtime·gc(2); // force GC and do eager sweep
runtime·lock(&runtime·mheap);
scavenge(-1, ~(uintptr)0, 0);
runtime·unlock(&runtime·mheap);