]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix freeOSMemory to free memory immediately
authorDmitriy Vyukov <dvyukov@google.com>
Mon, 19 May 2014 08:06:30 +0000 (12:06 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Mon, 19 May 2014 08:06:30 +0000 (12:06 +0400)
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

src/pkg/runtime/malloc.goc
src/pkg/runtime/mgc0.c
src/pkg/runtime/mheap.c

index 6371689a9c47500a19cb5fe923a9b86bc5657e6b..6e1068d93d2f0f7015f699bdb7e634b02baa06e0 100644 (file)
@@ -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) {
index 7152e3b37ced9b82efc82dd55b18ceee6903ae03..e51ce24ff6b3ce30f350dd2d7f5fcdb4dbc902da 100644 (file)
@@ -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);
index 3de6b8bb4ee0f85709441ef70062b3422a58a855..7e83eb2833d35a1b2d1e4dafcd6ad7035bb91e63 100644 (file)
@@ -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);