diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-03-07 21:56:40 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-03-07 21:56:40 +0000 |
commit | afcfc2fb252ab8b099a640a05d214646d42a192d (patch) | |
tree | 77fc6f6a82086f63737b0bac469fcd10a0cfe69d /libgo | |
parent | 82c96609f99686fbffb05228ddd27dc127f36128 (diff) | |
download | gcc-afcfc2fb252ab8b099a640a05d214646d42a192d.tar.gz |
Avoid race condition manipulating heap when goroutine exits.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@170758 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo')
-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 8c2de2877cf..3d8e9e62908 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); } |