Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GC Behavior and CLR Thread Hijacking

I was reading about the GC in the book CLR via C#, specifically about when the CLR wants to start a collection. I understand that it has to suspend the threads before a collection occurs, but it mentions that it has to do this when the thread instruction pointer reaches a safe point. In the cases where it's not in a safe point, it tries to get to one quickly, and it does so by hijacking the thread (inserting a special function pointer in the thread stack). That's all fine and dandy, but I thought managed threads by default were safe?

I had initially thought it might have been referring to unmanaged threads, but the CLR lets unmanaged threads continue executing because any object being used should have been pinned anyway.

So, what is a safe point in a managed thread, and how can the GC determine what that is?

EDIT:

I don't think I was being specific enough. According to this MSDN article, even when Thread.Suspend is called, the thread will not actually be suspended until a safe point is reached. It goes on to further state that a safe point is a point in a threads execution at which a garbage collection can be performed.

I think I was unclear in my question. I realize that a Thread can only be suspended at a safe point and they have to be suspended for a GC, but I can't seem to find a clear answer as to what a safe point is. What determines a point in code as being safe?

like image 581
Christopher Currens Avatar asked Dec 06 '11 17:12

Christopher Currens


1 Answers

'Safe Points' are where we are:

  1. Not in a catch block.
  2. Not inside a finally
  3. Not inside a lock
  4. Not inside p/invoke'd call (in managed code). Not running unmanaged code in the CLR.
  5. The memory tree is walkable.

Point #5 is a bit confusing, but there are times when the memory tree will not be walkable. For example, after optimization, the CLR may new an Object and not assign it directly to a variable. According to the GC, this object would be a dead object ready to be collected. The compiler will instruct the GC when this happens to not run GC yet.

Here's a blog post on msdn with a little bit more information: http://blogs.msdn.com/b/abhinaba/archive/2009/09/02/netcf-gc-and-thread-blocking.aspx

EDIT: Well, sir, I was WRONG about #4. See here in the 'Safe Point' section. If we are inside a p/invoke (unmanaged) code section then it is allowed to run until it comes back out to managed code again.

However, according to this MSDN article, if we are in an unmanaged portion of CLR code, then it is not considered safe and they will wait until the code returns to managed. (I was close, at least).

like image 142
DanTheMan Avatar answered Oct 06 '22 00:10

DanTheMan