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