From patchwork Tue Dec 14 05:16:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: libgo patch committed: Fix locking for release and allocate cache Date: Mon, 13 Dec 2010 19:16:27 -0000 From: Ian Taylor X-Patchwork-Id: 75468 Message-Id: To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com In the last libgo update I introduced a bug. I changed the code to not hold the thread_ids lock while releasing the cache. That was a mistake, because a garbage collection could occur after the thread_ids lock was released but before the cache was released. That could cause the thread's m structure to be released, which could in turn cause a null pointer dereference when updating statistics. Conversely, it is no longer necessary to hold the thread_ids lock while allocating the cache. Previously that served as a lock for runtime_mheap.cachealloc, but that is no longer necessary as the code now uses the runtime_mheap lock instead. This patch implements both changes. Committed to mainline. Ian diff -r 3ac32bd87c72 libgo/runtime/go-go.c --- a/libgo/runtime/go-go.c Thu Dec 09 15:54:35 2010 -0800 +++ b/libgo/runtime/go-go.c Mon Dec 13 21:11:03 2010 -0800 @@ -107,11 +107,11 @@ if (list_entry->next != NULL) list_entry->next->prev = list_entry->prev; + runtime_MCache_ReleaseAll (mcache); + i = pthread_mutex_unlock (&__go_thread_ids_lock); __go_assert (i == 0); - runtime_MCache_ReleaseAll (mcache); - runtime_lock (&runtime_mheap); mstats.heap_alloc += mcache->local_alloc; mstats.heap_objects += mcache->local_objects; @@ -225,14 +225,13 @@ newm->list_entry = list_entry; + newm->mcache = runtime_allocmcache (); + /* Add the thread to the list of all threads, marked as tentative since it is not yet ready to go. */ i = pthread_mutex_lock (&__go_thread_ids_lock); __go_assert (i == 0); - /* We use __go_thread_ids_lock as a lock for mheap.cachealloc. */ - newm->mcache = runtime_allocmcache (); - if (__go_all_thread_ids != NULL) __go_all_thread_ids->prev = list_entry; list_entry->next = __go_all_thread_ids;