Commit e893acf1 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

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
parent d021d982
...@@ -849,16 +849,7 @@ runtime·cnewarray(Type *typ, intgo n) ...@@ -849,16 +849,7 @@ runtime·cnewarray(Type *typ, intgo n)
} }
func GC() { func GC() {
// We assume that the user expects unused memory to have runtime·gc(2); // force GC and do eager sweep
// 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);
} }
func SetFinalizer(obj Eface, finalizer Eface) { func SetFinalizer(obj Eface, finalizer Eface) {
......
...@@ -2239,6 +2239,7 @@ runtime·updatememstats(GCStats *stats) ...@@ -2239,6 +2239,7 @@ runtime·updatememstats(GCStats *stats)
struct gc_args struct gc_args
{ {
int64 start_time; // start time of GC in ns (just before stoptheworld) int64 start_time; // start time of GC in ns (just before stoptheworld)
bool eagersweep;
}; };
static void gc(struct gc_args *args); static void gc(struct gc_args *args);
...@@ -2257,6 +2258,8 @@ readgogc(void) ...@@ -2257,6 +2258,8 @@ readgogc(void)
return runtime·atoi(p); return runtime·atoi(p);
} }
// force = 1 - do GC regardless of current heap usage
// force = 2 - go GC and eager sweep
void void
runtime·gc(int32 force) runtime·gc(int32 force)
{ {
...@@ -2292,7 +2295,7 @@ runtime·gc(int32 force) ...@@ -2292,7 +2295,7 @@ runtime·gc(int32 force)
return; return;
runtime·semacquire(&runtime·worldsema, false); 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 // typically threads which lost the race to grab
// worldsema exit here when gc is done. // worldsema exit here when gc is done.
runtime·semrelease(&runtime·worldsema); runtime·semrelease(&runtime·worldsema);
...@@ -2301,6 +2304,7 @@ runtime·gc(int32 force) ...@@ -2301,6 +2304,7 @@ runtime·gc(int32 force)
// Ok, we're doing it! Stop everybody else // Ok, we're doing it! Stop everybody else
a.start_time = runtime·nanotime(); a.start_time = runtime·nanotime();
a.eagersweep = force >= 2;
m->gcing = 1; m->gcing = 1;
runtime·stoptheworld(); runtime·stoptheworld();
...@@ -2490,7 +2494,7 @@ gc(struct gc_args *args) ...@@ -2490,7 +2494,7 @@ gc(struct gc_args *args)
sweep.spanidx = 0; sweep.spanidx = 0;
// Temporary disable concurrent sweep, because we see failures on builders. // Temporary disable concurrent sweep, because we see failures on builders.
if(ConcurrentSweep) { if(ConcurrentSweep && !args->eagersweep) {
runtime·lock(&gclock); runtime·lock(&gclock);
if(sweep.g == nil) if(sweep.g == nil)
sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, runtime·gc); sweep.g = runtime·newproc1(&bgsweepv, nil, 0, 0, runtime·gc);
......
...@@ -555,7 +555,7 @@ runtime·MHeap_Scavenger(void) ...@@ -555,7 +555,7 @@ runtime·MHeap_Scavenger(void)
void void
runtimedebug·freeOSMemory(void) runtimedebug·freeOSMemory(void)
{ {
runtime·gc(1); runtime·gc(2); // force GC and do eager sweep
runtime·lock(&runtime·mheap); runtime·lock(&runtime·mheap);
scavenge(-1, ~(uintptr)0, 0); scavenge(-1, ~(uintptr)0, 0);
runtime·unlock(&runtime·mheap); runtime·unlock(&runtime·mheap);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment