A caveat regarding comments in Rotor: sometimes there are comments left
from the commercial CLR that do not fully apply. For example, the
coordination mechanism in Rotor is considerably simpler than the
commercial CLR, since it is not pre-emptive, yet this is not fully
reflected in comments. (The commercial product *does* support
pre-emption...) 

Rotor always uses cooperative GC. Sometimes when unmanaged code is
running, the thread is said to be in pre-emptive mode, but this has
nothing to do with GC. (You are correct that this comes into play when
unmanaged code is executed. It might hold locks or other resources, and
should not be stopped, and so pre-emptive mode is used by Rotor in these
situations.)

Besides the confusing names for the modes, additional confusion may be
resulting from the fact that JIT_PollGC uses the toggle between
pre-emptive mode and cooperative mode to communicate with the garbage
collector (to "pulse"). Once a GC has begun on one thread, the calls to
JIT_PollGC on the other managed threads are equivalent to an assertion
that it is safe to GC. The thread that will perform the GC waits until
all threads currently in managed code have "checked in" using a two-step
mechanism described below to proceed. (See SysSuspendForGC in
threads.cpp for this logic. And, on quick inspection, not every comment
in this code is applicable to Rotor...)

Within the sync function, when Rotor calls the PAL's ::SuspendThread
function to "capture" a thread for GC, it checks to see whether the
thread is in cooperative mode or not.  If it *is* in cooperative mode,
the thread is suspended, the GCPending bit is set, and the thread is
resumed so that the next JIT_PollGC() will cause the thread to cede
control to the GC.  If the thread is running native code in preemptive
mode, the EE immediately resumes the thread, knowing that on its next
transition from unmanaged to managed, it will poll and allow the GC to
run. After this, the thread waits for all managed threads to raise
events, after which GC can happen. Once GC has finished, the GCPending
bit is cleared and away you go. (The m_SafeEvent field of Thread is the
actual event that is used to signal.)

FYI - the GC_PROTECT macros are for registering "roots" w/ the GC, as
you surmise. No relationship with what we are talking about here.

Hope that this is helpful.
-- David Stutz

Archana asked:

well it all started after i saw a block of comments in vm/threads.cpp
which mentions about sync and async suspension as i understand it, the
compiler emits calls to JIT_PollGC at safe points (this calls
CommonTripThread which is supposed to belong to the category of
synchronous suspension functions). so i wanted a clear picture of the
interaction happening between SysSuspendForGC and CommonTripThread.

And also i would be extremely grateful if you could explain about- the
Preemptive mode of the GC does this mode come into picture only when
unmanaged code is executed ? most of the references in the code indicate
that preemptive mode is enabled when there are calls to the OS / any
exceptions occuring etc.. i am not able to understand this part of the
functionality Is there any relation between this and the macros
GCPROTECT_BEGIN and GCPROTECT_END ? (they seem to push objects onto a
newly created frame which would be updated by the GC if it occurs etc..)

Reply via email to