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