summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-03-07 21:56:40 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-03-07 21:56:40 +0000
commitafcfc2fb252ab8b099a640a05d214646d42a192d (patch)
tree77fc6f6a82086f63737b0bac469fcd10a0cfe69d /libgo
parent82c96609f99686fbffb05228ddd27dc127f36128 (diff)
downloadgcc-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.c23
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);
}