SSCLI中GC垃圾回收源碼分析(2) - GarbageCollect()與Spin Lock
繼續接著上篇的分析,
F11從Fcall中跳出來,就到了sscli20\clr\src\vm\gcsmp.cpp中關于Garbage Collect的最外部的方法GCHeap::GarbageCollect:
HRESULT GCHeap::GarbageCollect (int generation, BOOL collect_classes_p) { UINT GenerationAtEntry = GcCount; //This loop is necessary for concurrent GC because //during concurrent GC we get in and out of //GarbageCollectGeneration without doing an independent GC do { enter_spin_lock (&gc_heap::more_space_lock); COUNTER_ONLY(GetPrivatePerfCounters().m_GC.cInducedGCs ++); int gen = (generation < 0) ? max_generation : min (generation, max_generation); GarbageCollectGeneration (gen, collect_classes_p); leave_spin_lock (&gc_heap::more_space_lock); } while (GenerationAtEntry == GcCount); return S_OK; }
這里使用一個do-While循環的主要目的,是由于在并發GC的時候,需要在不同的時間進進出出地調用GarbageCollectGeneration方法。而在一個非并發獨立的GC中,則不需要這種循環。
在enter_spin_lock和leave_spin_lock成對使用,這兩句的主要功能,就是訪問位于sscli20\clr\src\vm\gcsmppriv.h的GC Heap中定義的一個Spin Lock:
GCSpinLock more_space_lock; //lock while allocating more space
more_space_lock主要在以下三種情況下使用:
- 線程希望增加CPU分給這個線程的使用時間的時候。
- 線程在需要分配一大塊內存區域的時候。
- GarbageCollect在實現的時候,實際調用的是GarbageCollectGeneration方法,使用more_space_lock來阻止GarbageCollect之后程序直接調用GarbageCollectGeneration方法進行GC。
關于Spinlock的讀寫在SSCLI中的實現,可以在sscli20\clr\src\vm\gcsmp.cpp中找到:
inline static void enter_spin_lock (LONG volatile * lock) { retry: if (FastInterlockExchange (lock, 0) >= 0) { unsigned int i = 0; while (*lock >= 0) { if (++i & 7) __SwitchToThread (0); else { WaitLonger(i); } } goto retry; } }
這里, FastInterlockExchange是比較有意思的。Spinlock的實現,是一個thread對一個flag標志位通過死循環來不停的查詢,直到這個Flag可用為止。出于效率和安全性的多方面因素的考慮,因為一個object是否可以使用,是在object的synblock里面有一個bit位來標識spinlock的,因此這個地方的FastInterlockExchange的實現,是直接使用匯編代碼來高效的實現,可以在sscli20\clr\src\vm\i386\asmhelpers.asm文件中找到:
FASTCALL_FUNC ExchangeMP,8
_ASSERT_ALIGNED_4_X86 ecx
mov eax, [ecx] ; attempted comparand
retryMP:
lock cmpxchg [ecx], edx
jne retry1MP ; predicted NOT taken
retn
retry1MP:
jmp retryMP
FASTCALL_ENDFUNC ExchangeMP
對Spinlock的訪問就使用上面的代碼來一直讀,讀到相等就執行retn來退出,否則一直重復執行 cmpxchg指令來進行比較。
在得到lock之后,就到了GC的主要實現部分,位于sscli20\clr\src\vm\gcsmp.cpp中的GCHeap::GarbageCollectGeneration (unsigned int gen, BOOL collect_classes_p)。
posted on 2009-09-14 18:31 lbq1221119 閱讀(2484) 評論(2) 收藏 舉報
浙公網安備 33010602011771號