diff mbox

[gccgo] When a goroutine exits, free its mcache

Message ID mcraapes8j8.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor July 26, 2010, 12:59 p.m. UTC
In the gc compiler runtime, goroutines exit but OS threads never do.
This means that there is never a need to free the thread-specific memory
cache.

In gccgo, OS threads do exit.  And that means that we do need to free
the thread-specific cache when they exit.  That is what this patch does.

Interestingly, the garbage collector is fully able to free up all the
memory used by the cache.  However, it is not able to free the cache
itself.  This means that caches slowly accumulate over time as a new one
is allocated for each new goroutine.  A more important effect is that
each cache holds references to spans.  Not freeing the caches means that
the spans are never freed.  And that means that the spans are during
each garbage collection sweep, even though they no longer contain any
allocated memory.

Fixing this problem speeds up gccgo's garbage collection to take an
acceptable amount of time.

Committed to gccgo branch.

Ian
diff mbox

Patch

diff -r 4ccd6253e3e9 libgo/runtime/go-go.c
--- a/libgo/runtime/go-go.c	Mon Jul 26 04:21:01 2010 -0700
+++ b/libgo/runtime/go-go.c	Mon Jul 26 05:47:38 2010 -0700
@@ -114,6 +114,11 @@ 
 
   free (list_entry);
   m->list_entry = NULL;
+
+  MCache_ReleaseAll (m->mcache);
+  __builtin_memset (m->mcache, 0, sizeof (struct MCache));
+  FixAlloc_Free (&mheap.cachealloc, m->mcache);
+  m->mcache = NULL;
 }
 
 /* Start the thread.  */
@@ -511,7 +516,7 @@ 
   struct __go_thread_id *p;
 
   for (p = __go_all_thread_ids; p != NULL; p = p->next)
-    MCache_ReleaseAll(p->m->mcache);
+    MCache_ReleaseAll (p->m->mcache);
 }
 
 /* Start the other threads after garbage collection.  */
diff -r 4ccd6253e3e9 libgo/runtime/malloc.goc
--- a/libgo/runtime/malloc.goc	Mon Jul 26 04:21:01 2010 -0700
+++ b/libgo/runtime/malloc.goc	Mon Jul 26 05:47:38 2010 -0700
@@ -248,6 +248,10 @@ 
 	MCache *c;
 
 	c = FixAlloc_Alloc(&mheap.cachealloc);
+
+	// Clear the free list used by FixAlloc; assume the rest is zeroed.
+	c->list[0].list = nil;
+
 	mstats.mcache_inuse = mheap.cachealloc.inuse;
 	mstats.mcache_sys = mheap.cachealloc.sys;
 	return c;