diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-03-07 21:56:40 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-03-07 21:56:40 +0000 |
commit | 691a924baf30c73fd91a19b6b9679ab9da6e29b3 (patch) | |
tree | 77fc6f6a82086f63737b0bac469fcd10a0cfe69d | |
parent | 457186f6d55cc813cdb1cdcbfd75457930dacbd2 (diff) | |
download | gcc-691a924baf30c73fd91a19b6b9679ab9da6e29b3.zip gcc-691a924baf30c73fd91a19b6b9679ab9da6e29b3.tar.gz gcc-691a924baf30c73fd91a19b6b9679ab9da6e29b3.tar.bz2 |
Avoid race condition manipulating heap when goroutine exits.
From-SVN: r170758
-rw-r--r-- | libgo/runtime/go-go.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/libgo/runtime/go-go.c b/libgo/runtime/go-go.c index 8c2de28..3d8e9e6 100644 --- a/libgo/runtime/go-go.c +++ b/libgo/runtime/go-go.c @@ -92,25 +92,32 @@ remove_current_thread (void) if (list_entry->next != NULL) list_entry->next->prev = list_entry->prev; + /* This will look runtime_mheap as needed. */ runtime_MCache_ReleaseAll (mcache); + /* This should never deadlock--there shouldn't be any code that + holds the runtime_mheap lock when locking __go_thread_ids_lock. + We don't want to do this after releasing __go_thread_ids_lock + because it will mean that the garbage collector might run, and + the garbage collector does not try to lock runtime_mheap in all + cases since it knows it is running single-threaded. */ + runtime_lock (&runtime_mheap); + mstats.heap_alloc += mcache->local_alloc; + mstats.heap_objects += mcache->local_objects; + __builtin_memset (mcache, 0, sizeof (struct MCache)); + runtime_FixAlloc_Free (&runtime_mheap.cachealloc, mcache); + runtime_unlock (&runtime_mheap); + /* As soon as we release this look, a GC could run. Since this thread is no longer on the list, the GC will not find our M structure, so it could get freed at any time. That means that - any code from here to thread exit must not assume that the m is + any code from here to thread exit must not assume that m is valid. */ m = NULL; i = pthread_mutex_unlock (&__go_thread_ids_lock); __go_assert (i == 0); - runtime_lock (&runtime_mheap); - mstats.heap_alloc += mcache->local_alloc; - mstats.heap_objects += mcache->local_objects; - __builtin_memset (mcache, 0, sizeof (struct MCache)); - runtime_FixAlloc_Free (&runtime_mheap.cachealloc, mcache); - runtime_unlock (&runtime_mheap); - free (list_entry); } |