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 /*
7  * GCCOMMON.CPP
8  *
9  * Code common to both SVR and WKS gcs
10  */
11 
12 #include "common.h"
13 
14 #include "gcenv.h"
15 #include "gc.h"
16 
17 #ifdef FEATURE_SVR_GC
18 SVAL_IMPL_INIT(uint32_t,IGCHeap,gcHeapType,IGCHeap::GC_HEAP_INVALID);
19 #endif // FEATURE_SVR_GC
20 
21 SVAL_IMPL_INIT(uint32_t,IGCHeap,maxGeneration,2);
22 
23 IGCHeapInternal* g_theGCHeap;
24 
25 #ifdef FEATURE_STANDALONE_GC
26 IGCToCLR* g_theGCToCLR;
27 #endif // FEATURE_STANDALONE_GC
28 
29 #ifdef GC_CONFIG_DRIVEN
30 GARY_IMPL(size_t, gc_global_mechanisms, MAX_GLOBAL_GC_MECHANISMS_COUNT);
31 #endif //GC_CONFIG_DRIVEN
32 
33 #ifndef DACCESS_COMPILE
34 
35 #ifdef WRITE_BARRIER_CHECK
36 uint8_t* g_GCShadow;
37 uint8_t* g_GCShadowEnd;
38 uint8_t* g_shadow_lowest_address = NULL;
39 #endif
40 
41 uint32_t* g_gc_card_table;
42 uint8_t* g_gc_lowest_address  = 0;
43 uint8_t* g_gc_highest_address = 0;
44 bool g_fFinalizerRunOnShutDown = false;
45 
46 VOLATILE(int32_t) m_GCLock = -1;
47 
48 #ifdef GC_CONFIG_DRIVEN
record_global_mechanism(int mech_index)49 void record_global_mechanism (int mech_index)
50 {
51 	(gc_global_mechanisms[mech_index])++;
52 }
53 #endif //GC_CONFIG_DRIVEN
54 
55 int32_t g_bLowMemoryFromHost = 0;
56 
57 #ifdef WRITE_BARRIER_CHECK
58 
59 #define INVALIDGCVALUE (void *)((size_t)0xcccccccd)
60 
61     // called by the write barrier to update the shadow heap
updateGCShadow(Object ** ptr,Object * val)62 void updateGCShadow(Object** ptr, Object* val)
63 {
64     Object** shadow = (Object**) &g_GCShadow[((uint8_t*) ptr - g_lowest_address)];
65     if ((uint8_t*) shadow < g_GCShadowEnd)
66     {
67         *shadow = val;
68 
69         // Ensure that the write to the shadow heap occurs before the read from
70         // the GC heap so that race conditions are caught by INVALIDGCVALUE.
71         MemoryBarrier();
72 
73         if(*ptr!=val)
74             *shadow = (Object *) INVALIDGCVALUE;
75     }
76 }
77 
78 #endif // WRITE_BARRIER_CHECK
79 
80 
81 struct changed_seg
82 {
83     uint8_t           * start;
84     uint8_t           * end;
85     size_t              gc_index;
86     bgc_state           bgc;
87     changed_seg_state   changed;
88 };
89 
90 
91 const int max_saved_changed_segs = 128;
92 
93 changed_seg saved_changed_segs[max_saved_changed_segs];
94 int saved_changed_segs_count = 0;
95 
record_changed_seg(uint8_t * start,uint8_t * end,size_t current_gc_index,bgc_state current_bgc_state,changed_seg_state changed_state)96 void record_changed_seg (uint8_t* start, uint8_t* end,
97                          size_t current_gc_index,
98                          bgc_state current_bgc_state,
99                          changed_seg_state changed_state)
100 {
101     if (saved_changed_segs_count < max_saved_changed_segs)
102     {
103         saved_changed_segs[saved_changed_segs_count].start = start;
104         saved_changed_segs[saved_changed_segs_count].end = end;
105         saved_changed_segs[saved_changed_segs_count].gc_index = current_gc_index;
106         saved_changed_segs[saved_changed_segs_count].bgc = current_bgc_state;
107         saved_changed_segs[saved_changed_segs_count].changed = changed_state;
108         saved_changed_segs_count++;
109     }
110     else
111     {
112         saved_changed_segs_count = 0;
113     }
114 }
115 
116 // The runtime needs to know whether we're using workstation or server GC
117 // long before the GCHeap is created.
InitializeHeapType(bool bServerHeap)118 void InitializeHeapType(bool bServerHeap)
119 {
120     LIMITED_METHOD_CONTRACT;
121 #ifdef FEATURE_SVR_GC
122     IGCHeap::gcHeapType = bServerHeap ? IGCHeap::GC_HEAP_SVR : IGCHeap::GC_HEAP_WKS;
123 #ifdef WRITE_BARRIER_CHECK
124     if (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR)
125     {
126         g_GCShadow = 0;
127         g_GCShadowEnd = 0;
128     }
129 #endif // WRITE_BARRIER_CHECK
130 #else // FEATURE_SVR_GC
131     UNREFERENCED_PARAMETER(bServerHeap);
132     CONSISTENCY_CHECK(bServerHeap == false);
133 #endif // FEATURE_SVR_GC
134 }
135 
InitializeGarbageCollector(IGCToCLR * clrToGC)136 IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC)
137 {
138     LIMITED_METHOD_CONTRACT;
139 
140     IGCHeapInternal* heap;
141 #ifdef FEATURE_SVR_GC
142     assert(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID);
143     heap = IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR ? SVR::CreateGCHeap() : WKS::CreateGCHeap();
144 #else
145     heap = WKS::CreateGCHeap();
146 #endif
147 
148     g_theGCHeap = heap;
149 
150 #ifdef FEATURE_STANDALONE_GC
151     assert(clrToGC != nullptr);
152     g_theGCToCLR = clrToGC;
153 #else
154     UNREFERENCED_PARAMETER(clrToGC);
155     assert(clrToGC == nullptr);
156 #endif
157 
158     return heap;
159 }
160 
161 #endif // !DACCESS_COMPILE
162