diff options
Diffstat (limited to 'src/vm/syncclean.cpp')
-rw-r--r-- | src/vm/syncclean.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/vm/syncclean.cpp b/src/vm/syncclean.cpp new file mode 100644 index 0000000000..e02c2f90c2 --- /dev/null +++ b/src/vm/syncclean.cpp @@ -0,0 +1,103 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#include "common.h" + +#include "syncclean.hpp" +#include "virtualcallstub.h" +#include "threadsuspend.h" + +VolatilePtr<Bucket> SyncClean::m_HashMap = NULL; +VolatilePtr<EEHashEntry*> SyncClean::m_EEHashTable; + +void SyncClean::Terminate() +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + } CONTRACTL_END; + + CleanUp(); +} + +void SyncClean::AddHashMap (Bucket *bucket) +{ + WRAPPER_NO_CONTRACT; + + if (!g_fEEStarted) { + delete [] bucket; + return; + } + + BEGIN_GETTHREAD_ALLOWED + _ASSERTE (GetThread() == NULL || GetThread()->PreemptiveGCDisabled()); + END_GETTHREAD_ALLOWED + + Bucket * pTempBucket = NULL; + do + { + pTempBucket = (Bucket *)m_HashMap; + NextObsolete (bucket) = pTempBucket; + } + while (FastInterlockCompareExchangePointer(m_HashMap.GetPointer(), bucket, pTempBucket) != pTempBucket); +} + +void SyncClean::AddEEHashTable (EEHashEntry** entry) +{ + WRAPPER_NO_CONTRACT; + + if (!g_fEEStarted) { + delete [] (entry-1); + return; + } + + BEGIN_GETTHREAD_ALLOWED + _ASSERTE (GetThread() == NULL || GetThread()->PreemptiveGCDisabled()); + END_GETTHREAD_ALLOWED + + EEHashEntry ** pTempHashEntry = NULL; + do + { + pTempHashEntry = (EEHashEntry**)m_EEHashTable; + entry[-1] = (EEHashEntry *)pTempHashEntry; + } + while (FastInterlockCompareExchangePointer(m_EEHashTable.GetPointer(), entry, pTempHashEntry) != pTempHashEntry); +} + +void SyncClean::CleanUp () +{ + LIMITED_METHOD_CONTRACT; + + // Only GC thread can call this. + _ASSERTE (g_fProcessDetach || + IsGCSpecialThread() || + (GCHeap::IsGCInProgress() && GetThread() == ThreadSuspend::GetSuspensionThread())); + if (m_HashMap) + { + Bucket * pTempBucket = FastInterlockExchangePointer(m_HashMap.GetPointer(), NULL); + + while (pTempBucket) + { + Bucket* pNextBucket = NextObsolete (pTempBucket); + delete [] pTempBucket; + pTempBucket = pNextBucket; + } + } + + if (m_EEHashTable) + { + EEHashEntry ** pTempHashEntry = FastInterlockExchangePointer(m_EEHashTable.GetPointer(), NULL); + + while (pTempHashEntry) { + EEHashEntry **pNextHashEntry = (EEHashEntry **)pTempHashEntry[-1]; + pTempHashEntry --; + delete [] pTempHashEntry; + pTempHashEntry = pNextHashEntry; + } + } + + // Give others we want to reclaim during the GC sync point a chance to do it + VirtualCallStubManager::ReclaimAll(); +} |