1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6#include "common.h"
7
8#include "syncclean.hpp"
9#include "virtualcallstub.h"
10#include "threadsuspend.h"
11
12VolatilePtr<Bucket> SyncClean::m_HashMap = NULL;
13VolatilePtr<EEHashEntry*> SyncClean::m_EEHashTable;
14
15void SyncClean::Terminate()
16{
17 CONTRACTL {
18 NOTHROW;
19 GC_NOTRIGGER;
20 } CONTRACTL_END;
21
22 CleanUp();
23}
24
25void SyncClean::AddHashMap (Bucket *bucket)
26{
27 WRAPPER_NO_CONTRACT;
28
29 if (!g_fEEStarted) {
30 delete [] bucket;
31 return;
32 }
33
34 BEGIN_GETTHREAD_ALLOWED
35 _ASSERTE (GetThread() == NULL || GetThread()->PreemptiveGCDisabled());
36 END_GETTHREAD_ALLOWED
37
38 Bucket * pTempBucket = NULL;
39 do
40 {
41 pTempBucket = (Bucket *)m_HashMap;
42 NextObsolete (bucket) = pTempBucket;
43 }
44 while (FastInterlockCompareExchangePointer(m_HashMap.GetPointer(), bucket, pTempBucket) != pTempBucket);
45}
46
47void SyncClean::AddEEHashTable (EEHashEntry** entry)
48{
49 WRAPPER_NO_CONTRACT;
50
51 if (!g_fEEStarted) {
52 delete [] (entry-1);
53 return;
54 }
55
56 BEGIN_GETTHREAD_ALLOWED
57 _ASSERTE (GetThread() == NULL || GetThread()->PreemptiveGCDisabled());
58 END_GETTHREAD_ALLOWED
59
60 EEHashEntry ** pTempHashEntry = NULL;
61 do
62 {
63 pTempHashEntry = (EEHashEntry**)m_EEHashTable;
64 entry[-1] = (EEHashEntry *)pTempHashEntry;
65 }
66 while (FastInterlockCompareExchangePointer(m_EEHashTable.GetPointer(), entry, pTempHashEntry) != pTempHashEntry);
67}
68
69void SyncClean::CleanUp ()
70{
71 LIMITED_METHOD_CONTRACT;
72
73 // Only GC thread can call this.
74 _ASSERTE (g_fProcessDetach ||
75 IsGCSpecialThread() ||
76 (GCHeapUtilities::IsGCInProgress() && GetThread() == ThreadSuspend::GetSuspensionThread()));
77 if (m_HashMap)
78 {
79 Bucket * pTempBucket = FastInterlockExchangePointer(m_HashMap.GetPointer(), NULL);
80
81 while (pTempBucket)
82 {
83 Bucket* pNextBucket = NextObsolete (pTempBucket);
84 delete [] pTempBucket;
85 pTempBucket = pNextBucket;
86 }
87 }
88
89 if (m_EEHashTable)
90 {
91 EEHashEntry ** pTempHashEntry = FastInterlockExchangePointer(m_EEHashTable.GetPointer(), NULL);
92
93 while (pTempHashEntry) {
94 EEHashEntry **pNextHashEntry = (EEHashEntry **)pTempHashEntry[-1];
95 pTempHashEntry --;
96 delete [] pTempHashEntry;
97 pTempHashEntry = pNextHashEntry;
98 }
99 }
100
101 // Give others we want to reclaim during the GC sync point a chance to do it
102 VirtualCallStubManager::ReclaimAll();
103}
104