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 #ifndef GCIMPL_H_
7 #define GCIMPL_H_
8
9 #define CLREvent CLREventStatic
10
11 #ifdef SERVER_GC
12 #define MULTIPLE_HEAPS 1
13 #endif // SERVER_GC
14
15 #ifdef MULTIPLE_HEAPS
16
17 #define PER_HEAP
18
19 #else //MULTIPLE_HEAPS
20
21 #define PER_HEAP static
22
23 #endif // MULTIPLE_HEAPS
24
25 #define PER_HEAP_ISOLATED static
26
27 #if defined(WRITE_BARRIER_CHECK) && !defined (MULTIPLE_HEAPS)
28 void initGCShadow();
29 void deleteGCShadow();
30 void checkGCWriteBarrier();
31 #else
initGCShadow()32 inline void initGCShadow() {}
deleteGCShadow()33 inline void deleteGCShadow() {}
checkGCWriteBarrier()34 inline void checkGCWriteBarrier() {}
35 #endif
36
37 void GCProfileWalkHeap();
38
39 class gc_heap;
40 class CFinalize;
41
42 class GCHeap : public IGCHeapInternal
43 {
44 protected:
45
46 #ifdef MULTIPLE_HEAPS
47 gc_heap* pGenGCHeap;
48 #else
49 #define pGenGCHeap ((gc_heap*)0)
50 #endif //MULTIPLE_HEAPS
51
52 friend class CFinalize;
53 friend class gc_heap;
54 friend struct ::alloc_context;
55 friend void EnterAllocLock();
56 friend void LeaveAllocLock();
57 friend void ProfScanRootsHelper(Object** object, ScanContext *pSC, uint32_t dwFlags);
58 friend void GCProfileWalkHeap();
59
60 public:
61 //In order to keep gc.cpp cleaner, ugly EE specific code is relegated to methods.
62 static void UpdatePreGCCounters();
63 static void UpdatePostGCCounters();
64
65 public:
GCHeap()66 GCHeap(){};
~GCHeap()67 ~GCHeap(){};
68
69 /* BaseGCHeap Methods*/
70 PER_HEAP_ISOLATED HRESULT Shutdown ();
71
72 size_t GetTotalBytesInUse ();
73 // Gets the amount of bytes objects currently occupy on the GC heap.
74 size_t GetCurrentObjSize();
75
76 size_t GetLastGCStartTime(int generation);
77 size_t GetLastGCDuration(int generation);
78 size_t GetNow();
79
80 void DiagTraceGCSegments ();
81 void PublishObject(uint8_t* obj);
82
83 BOOL IsGCInProgressHelper (BOOL bConsiderGCStart = FALSE);
84
85 uint32_t WaitUntilGCComplete (BOOL bConsiderGCStart = FALSE);
86
87 void SetGCInProgress(BOOL fInProgress);
88
89 CLREvent * GetWaitForGCEvent();
90
91 HRESULT Initialize ();
92
93 //flags can be GC_ALLOC_CONTAINS_REF GC_ALLOC_FINALIZE
94 Object* Alloc (size_t size, uint32_t flags);
95 Object* AllocAlign8 (size_t size, uint32_t flags);
96 Object* AllocAlign8 (gc_alloc_context* acontext, size_t size, uint32_t flags);
97 private:
98 Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags);
99 public:
100 Object* AllocLHeap (size_t size, uint32_t flags);
101 Object* Alloc (gc_alloc_context* acontext, size_t size, uint32_t flags);
102
103 void FixAllocContext (gc_alloc_context* acontext,
104 BOOL lockp, void* arg, void *heap);
105
106 Object* GetContainingObject(void *pInteriorPtr);
107
108 #ifdef MULTIPLE_HEAPS
109 static void AssignHeap (alloc_context* acontext);
110 static GCHeap* GetHeap (int);
111 #endif //MULTIPLE_HEAPS
112
113 int GetHomeHeapNumber ();
114 bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number);
115 int GetNumberOfHeaps ();
116 void HideAllocContext(alloc_context*);
117 void RevealAllocContext(alloc_context*);
118
119 BOOL IsObjectInFixedHeap(Object *pObj);
120
121 HRESULT GarbageCollect (int generation = -1, BOOL low_memory_p=FALSE, int mode=collection_blocking);
122
123 ////
124 // GC callback functions
125 // Check if an argument is promoted (ONLY CALL DURING
126 // THE PROMOTIONSGRANTED CALLBACK.)
127 BOOL IsPromoted (Object *object);
128
129 size_t GetPromotedBytes (int heap_index);
130
131 int CollectionCount (int generation, int get_bgc_fgc_count = 0);
132
133 // promote an object
134 PER_HEAP_ISOLATED void Promote (Object** object,
135 ScanContext* sc,
136 uint32_t flags=0);
137
138 // Find the relocation address for an object
139 PER_HEAP_ISOLATED void Relocate (Object** object,
140 ScanContext* sc,
141 uint32_t flags=0);
142
143
144 HRESULT Init (size_t heapSize);
145
146 //Register an object for finalization
147 bool RegisterForFinalization (int gen, Object* obj);
148
149 //Unregister an object for finalization
150 void SetFinalizationRun (Object* obj);
151
152 //returns the generation number of an object (not valid during relocation)
153 unsigned WhichGeneration (Object* object);
154 // returns TRUE is the object is ephemeral
155 BOOL IsEphemeral (Object* object);
156 BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE);
157
158 void ValidateObjectMember (Object *obj);
159
160 PER_HEAP size_t ApproxTotalBytesInUse(BOOL small_heap_only = FALSE);
161 PER_HEAP size_t ApproxFreeBytes();
162
163 unsigned GetCondemnedGeneration();
164
165 int GetGcLatencyMode();
166 int SetGcLatencyMode(int newLatencyMode);
167
168 int GetLOHCompactionMode();
169 void SetLOHCompactionMode(int newLOHCompactionyMode);
170
171 BOOL RegisterForFullGCNotification(uint32_t gen2Percentage,
172 uint32_t lohPercentage);
173 BOOL CancelFullGCNotification();
174 int WaitForFullGCApproach(int millisecondsTimeout);
175 int WaitForFullGCComplete(int millisecondsTimeout);
176
177 int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC);
178 int EndNoGCRegion();
179
180 unsigned GetGcCount();
181
GetNextFinalizable()182 Object* GetNextFinalizable() { return GetNextFinalizableObject(); };
GetNumberOfFinalizable()183 size_t GetNumberOfFinalizable() { return GetNumberFinalizableObjects(); }
184
185 PER_HEAP_ISOLATED HRESULT GetGcCounters(int gen, gc_counters* counters);
186
187 size_t GetValidSegmentSize(BOOL large_seg = FALSE);
188
189 static size_t GetValidGen0MaxSize(size_t seg_size);
190
191 void SetReservedVMLimit (size_t vmlimit);
192
193 PER_HEAP_ISOLATED Object* GetNextFinalizableObject();
194 PER_HEAP_ISOLATED size_t GetNumberFinalizableObjects();
195 PER_HEAP_ISOLATED size_t GetFinalizablePromotedCount();
196
197 void SetFinalizeQueueForShutdown(BOOL fHasLock);
198 BOOL FinalizeAppDomain(AppDomain *pDomain, BOOL fRunFinalizers);
199 BOOL ShouldRestartFinalizerWatchDog();
200
201 void DiagWalkObject (Object* obj, walk_fn fn, void* context);
202
203 public: // FIX
204
205 // Lock for finalization
206 PER_HEAP_ISOLATED
207 VOLATILE(int32_t) m_GCFLock;
208
209 PER_HEAP_ISOLATED BOOL GcCollectClasses;
210 PER_HEAP_ISOLATED
211 VOLATILE(BOOL) GcInProgress; // used for syncing w/GC
212 PER_HEAP_ISOLATED VOLATILE(unsigned) GcCount;
213 PER_HEAP_ISOLATED unsigned GcCondemnedGeneration;
214 // calculated at the end of a GC.
215 PER_HEAP_ISOLATED size_t totalSurvivedSize;
216
217 // Use only for GC tracing.
218 PER_HEAP unsigned int GcDuration;
219
220 size_t GarbageCollectGeneration (unsigned int gen=0, gc_reason reason=reason_empty);
221 // Interface with gc_heap
222 size_t GarbageCollectTry (int generation, BOOL low_memory_p=FALSE, int mode=collection_blocking);
223
224 // frozen segment management functions
225 virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo);
226 virtual void UnregisterFrozenSegment(segment_handle seg);
227
228 void WaitUntilConcurrentGCComplete (); // Use in managd threads
229 #ifndef DACCESS_COMPILE
230 HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout); // Use in native threads. TRUE if succeed. FALSE if failed or timeout
231 #endif
232 BOOL IsConcurrentGCInProgress();
233
234 // Enable/disable concurrent GC
235 void TemporaryEnableConcurrentGC();
236 void TemporaryDisableConcurrentGC();
237 BOOL IsConcurrentGCEnabled();
238
239 PER_HEAP_ISOLATED CLREvent *WaitForGCEvent; // used for syncing w/GC
240
241 PER_HEAP_ISOLATED CFinalize* m_Finalize;
242
243 PER_HEAP_ISOLATED gc_heap* Getgc_heap();
244
245 private:
SafeToRestartManagedThreads()246 static bool SafeToRestartManagedThreads()
247 {
248 // Note: this routine should return true when the last barrier
249 // to threads returning to cooperative mode is down after gc.
250 // In other words, if the sequence in GCHeap::RestartEE changes,
251 // the condition here may have to change as well.
252 return g_TrapReturningThreads == 0;
253 }
254 public:
255 //return TRUE if GC actually happens, otherwise FALSE
256 BOOL StressHeap(gc_alloc_context * acontext = 0);
257
258 #ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way
259 #ifdef STRESS_HEAP
260 protected:
261
262 // only used in BACKGROUND_GC, but the symbol is not defined yet...
263 PER_HEAP_ISOLATED int gc_stress_fgcs_in_bgc;
264
265 #if !defined(MULTIPLE_HEAPS)
266 // handles to hold the string objects that will force GC movement
267 enum { NUM_HEAP_STRESS_OBJS = 8 };
268 PER_HEAP OBJECTHANDLE m_StressObjs[NUM_HEAP_STRESS_OBJS];
269 PER_HEAP int m_CurStressObj;
270 #endif // !defined(MULTIPLE_HEAPS)
271 #endif // STRESS_HEAP
272 #endif // FEATURE_REDHAWK
273
274 virtual void DiagDescrGenerations (gen_walk_fn fn, void *context);
275
276 virtual void DiagWalkSurvivorsWithType (void* gc_context, record_surv_fn fn, size_t diag_context, walk_surv_type type);
277
278 virtual void DiagWalkFinalizeQueue (void* gc_context, fq_walk_fn fn);
279
280 virtual void DiagScanFinalizeQueue (fq_scan_fn fn, ScanContext* context);
281
282 virtual void DiagScanHandles (handle_scan_fn fn, int gen_number, ScanContext* context);
283
284 virtual void DiagScanDependentHandles (handle_scan_fn fn, int gen_number, ScanContext* context);
285
286 virtual void DiagWalkHeap(walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p);
287
288 public:
289 Object * NextObj (Object * object);
290 #if defined (FEATURE_BASICFREEZE) && defined (VERIFY_HEAP)
291 BOOL IsInFrozenSegment (Object * object);
292 #endif // defined (FEATURE_BASICFREEZE) && defined (VERIFY_HEAP)
293 };
294
295 #endif // GCIMPL_H_
296