mirror of git://gcc.gnu.org/git/gcc.git
Avoid race condition manipulating heap when goroutine exits.
From-SVN: r170758
This commit is contained in:
parent
457186f6d5
commit
691a924baf
|
@ -92,18 +92,15 @@ remove_current_thread (void)
|
||||||
if (list_entry->next != NULL)
|
if (list_entry->next != NULL)
|
||||||
list_entry->next->prev = list_entry->prev;
|
list_entry->next->prev = list_entry->prev;
|
||||||
|
|
||||||
|
/* This will look runtime_mheap as needed. */
|
||||||
runtime_MCache_ReleaseAll (mcache);
|
runtime_MCache_ReleaseAll (mcache);
|
||||||
|
|
||||||
/* As soon as we release this look, a GC could run. Since this
|
/* This should never deadlock--there shouldn't be any code that
|
||||||
thread is no longer on the list, the GC will not find our M
|
holds the runtime_mheap lock when locking __go_thread_ids_lock.
|
||||||
structure, so it could get freed at any time. That means that
|
We don't want to do this after releasing __go_thread_ids_lock
|
||||||
any code from here to thread exit must not assume that the m is
|
because it will mean that the garbage collector might run, and
|
||||||
valid. */
|
the garbage collector does not try to lock runtime_mheap in all
|
||||||
m = NULL;
|
cases since it knows it is running single-threaded. */
|
||||||
|
|
||||||
i = pthread_mutex_unlock (&__go_thread_ids_lock);
|
|
||||||
__go_assert (i == 0);
|
|
||||||
|
|
||||||
runtime_lock (&runtime_mheap);
|
runtime_lock (&runtime_mheap);
|
||||||
mstats.heap_alloc += mcache->local_alloc;
|
mstats.heap_alloc += mcache->local_alloc;
|
||||||
mstats.heap_objects += mcache->local_objects;
|
mstats.heap_objects += mcache->local_objects;
|
||||||
|
@ -111,6 +108,16 @@ remove_current_thread (void)
|
||||||
runtime_FixAlloc_Free (&runtime_mheap.cachealloc, mcache);
|
runtime_FixAlloc_Free (&runtime_mheap.cachealloc, mcache);
|
||||||
runtime_unlock (&runtime_mheap);
|
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 m is
|
||||||
|
valid. */
|
||||||
|
m = NULL;
|
||||||
|
|
||||||
|
i = pthread_mutex_unlock (&__go_thread_ids_lock);
|
||||||
|
__go_assert (i == 0);
|
||||||
|
|
||||||
free (list_entry);
|
free (list_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue