Fix the ordering of lock acquisition in the heap worker.

A feature of the concurrent GC is that gcHeapLock is released while
roots are traced through.  This complicates the heap worker thread as
it assumes that when the gcHeapLock can be acquired no threads are
contending for the heapWorkerLock.  However, the concurrent GC holds
heapWorkerLock for the duration of a GC.  If the heap worker thread
becomes active while the GC temporarily release gcHeapLock it may
deadlock the GC by acquring the gcHeapLock, needed by the GC during
its final pause, and wait for the heapWorkerLock held by the GC.

This change attempts to resolve this issue by checking to see if after
a transition into running whether the GC has become active.  If so, it
releases gcHeapLock and reacquires it after the GC has signaled
completion.  This must be done in a loop as there is no guarantee that
the GC has not become active when heap worker is rescheduled.
1 file changed