diff mbox

[gccgo] Use __go_thread_ids_lock to lock mcache alloc and free

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

Commit Message

Ian Lance Taylor Aug. 1, 2010, 10:20 a.m. UTC
There is no lock on the FixAlloc used to allocate and free mcache
structures.  With this patch, we use __go_thread_ids_lock as a lock for
it.  This also fixes the problem of accessing the mcache field of an M
structure which has been freed by the garbage collector after the thread
has been taken off the list of all threads.  Committed to gccgo branch.

Ian
diff mbox

Patch

diff -r 18d3fecdcc06 libgo/runtime/go-go.c
--- a/libgo/runtime/go-go.c	Wed Jul 28 09:07:42 2010 -0700
+++ b/libgo/runtime/go-go.c	Sun Aug 01 03:16:41 2010 -0700
@@ -91,9 +91,11 @@ 
 remove_current_thread (void)
 {
   struct __go_thread_id *list_entry;
+  MCache *mcache;
   int i;
   
   list_entry = m->list_entry;
+  mcache = m->mcache;
 
   i = pthread_mutex_lock (&__go_thread_ids_lock);
   assert (i == 0);
@@ -105,16 +107,15 @@ 
   if (list_entry->next != NULL)
     list_entry->next->prev = list_entry->prev;
 
+  /* We use __go_thread_ids_lock as a lock for mheap.cachealloc.  */
+  MCache_ReleaseAll (mcache);
+  __builtin_memset (mcache, 0, sizeof (struct MCache));
+  FixAlloc_Free (&mheap.cachealloc, mcache);
+
   i = pthread_mutex_unlock (&__go_thread_ids_lock);
   assert (i == 0);
 
   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.  */
@@ -209,7 +210,6 @@ 
 #endif
 
   newm = __go_alloc (sizeof (M));
-  newm->mcache = allocmcache ();
 
   list_entry = malloc (sizeof (struct __go_thread_id));
   list_entry->prev = NULL;
@@ -226,6 +226,9 @@ 
   i = pthread_mutex_lock (&__go_thread_ids_lock);
   assert (i == 0);
 
+  /* We use __go_thread_ids_lock as a lock for mheap.cachealloc.  */
+  newm->mcache = allocmcache ();
+
   if (__go_all_thread_ids != NULL)
     __go_all_thread_ids->prev = list_entry;
   list_entry->next = __go_all_thread_ids;