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
8Module Name:
9
10 gc.h
11
12--*/
13
14#ifndef __GC_H
15#define __GC_H
16
17#include "gcinterface.h"
18#include "env/gcenv.os.h"
19
20#ifdef BUILD_AS_STANDALONE
21#include "gcenv.ee.standalone.inl"
22
23// GCStress does not currently work with Standalone GC
24#ifdef STRESS_HEAP
25 #undef STRESS_HEAP
26#endif // STRESS_HEAP
27#else
28#include "env/gcenv.ee.h"
29#endif // BUILD_AS_STANDALONE
30#include "gcconfig.h"
31
32/*
33 * Promotion Function Prototypes
34 */
35typedef void enum_func (Object*);
36
37// callback functions for heap walkers
38typedef void object_callback_func(void * pvContext, void * pvDataLoc);
39
40struct fgm_history
41{
42 failure_get_memory fgm;
43 size_t size;
44 size_t available_pagefile_mb;
45 BOOL loh_p;
46
47 void set_fgm (failure_get_memory f, size_t s, BOOL l)
48 {
49 fgm = f;
50 size = s;
51 loh_p = l;
52 }
53};
54
55// These values should be in sync with the GC_REASONs (in eventtrace.h) used for ETW.
56// TODO : it would be easier to make this an ORed value
57enum gc_reason
58{
59 reason_alloc_soh = 0,
60 reason_induced = 1,
61 reason_lowmemory = 2,
62 reason_empty = 3,
63 reason_alloc_loh = 4,
64 reason_oos_soh = 5,
65 reason_oos_loh = 6,
66 reason_induced_noforce = 7, // it's an induced GC and doesn't have to be blocking.
67 reason_gcstress = 8, // this turns into reason_induced & gc_mechanisms.stress_induced = true
68 reason_lowmemory_blocking = 9,
69 reason_induced_compacting = 10,
70 reason_lowmemory_host = 11,
71 reason_pm_full_gc = 12, // provisional mode requested to trigger full GC
72 reason_lowmemory_host_blocking = 13,
73 reason_max
74};
75
76// Types of GCs, emitted by the GCStart ETW event.
77enum gc_etw_type
78{
79 gc_etw_type_ngc = 0,
80 gc_etw_type_bgc = 1,
81 gc_etw_type_fgc = 2
82};
83
84// Types of segments, emitted by the GCCreateSegment ETW event.
85enum gc_etw_segment_type
86{
87 gc_etw_segment_small_object_heap = 0,
88 gc_etw_segment_large_object_heap = 1,
89 gc_etw_segment_read_only_heap = 2
90};
91
92// Types of allocations, emitted by the GCAllocationTick ETW event.
93enum gc_etw_alloc_kind
94{
95 gc_etw_alloc_soh = 0,
96 gc_etw_alloc_loh = 1
97};
98
99/* forward declerations */
100class CObjectHeader;
101class Object;
102
103class IGCHeapInternal;
104
105/* misc defines */
106#define LARGE_OBJECT_SIZE ((size_t)(85000))
107#define max_generation 2
108
109#ifdef GC_CONFIG_DRIVEN
110#define MAX_GLOBAL_GC_MECHANISMS_COUNT 6
111extern size_t gc_global_mechanisms[MAX_GLOBAL_GC_MECHANISMS_COUNT];
112#endif //GC_CONFIG_DRIVEN
113
114#ifdef DACCESS_COMPILE
115class DacHeapWalker;
116#endif
117
118#ifdef _DEBUG
119#define _LOGALLOC
120#endif
121
122#define MP_LOCKS
123
124#ifdef FEATURE_MANUALLY_MANAGED_CARD_BUNDLES
125extern "C" uint32_t* g_gc_card_bundle_table;
126#endif
127
128#if defined(ENABLE_PERF_COUNTERS) || defined(FEATURE_EVENT_TRACE)
129// Note this is not updated in a thread safe way so the value may not be accurate. We get
130// it accurately in full GCs if the handle count is requested.
131extern DWORD g_dwHandles;
132#endif // ENABLE_PERF_COUNTERS || FEATURE_EVENT_TRACE
133
134extern "C" uint32_t* g_gc_card_table;
135extern "C" uint8_t* g_gc_lowest_address;
136extern "C" uint8_t* g_gc_highest_address;
137extern "C" GCHeapType g_gc_heap_type;
138extern "C" uint32_t g_max_generation;
139extern "C" MethodTable* g_gc_pFreeObjectMethodTable;
140extern "C" uint32_t g_num_processors;
141
142extern VOLATILE(int32_t) g_fSuspensionPending;
143
144extern uint32_t g_yieldProcessorScalingFactor;
145
146::IGCHandleManager* CreateGCHandleManager();
147
148namespace WKS {
149 ::IGCHeapInternal* CreateGCHeap();
150 class GCHeap;
151 class gc_heap;
152 }
153
154#if defined(FEATURE_SVR_GC)
155namespace SVR {
156 ::IGCHeapInternal* CreateGCHeap();
157 class GCHeap;
158 class gc_heap;
159}
160#endif // defined(FEATURE_SVR_GC)
161
162#ifdef STRESS_HEAP
163#define IN_STRESS_HEAP(x) x
164#define STRESS_HEAP_ARG(x) ,x
165#else // STRESS_HEAP
166#define IN_STRESS_HEAP(x)
167#define STRESS_HEAP_ARG(x)
168#endif // STRESS_HEAP
169
170//dynamic data interface
171struct gc_counters
172{
173 size_t current_size;
174 size_t promoted_size;
175 size_t collection_count;
176};
177
178enum bgc_state
179{
180 bgc_not_in_process = 0,
181 bgc_initialized,
182 bgc_reset_ww,
183 bgc_mark_handles,
184 bgc_mark_stack,
185 bgc_revisit_soh,
186 bgc_revisit_loh,
187 bgc_overflow_soh,
188 bgc_overflow_loh,
189 bgc_final_marking,
190 bgc_sweep_soh,
191 bgc_sweep_loh,
192 bgc_plan_phase
193};
194
195enum changed_seg_state
196{
197 seg_deleted,
198 seg_added
199};
200
201void record_changed_seg (uint8_t* start, uint8_t* end,
202 size_t current_gc_index,
203 bgc_state current_bgc_state,
204 changed_seg_state changed_state);
205
206#ifdef GC_CONFIG_DRIVEN
207void record_global_mechanism (int mech_index);
208#endif //GC_CONFIG_DRIVEN
209
210struct alloc_context : gc_alloc_context
211{
212#ifdef FEATURE_SVR_GC
213 inline SVR::GCHeap* get_alloc_heap()
214 {
215 return static_cast<SVR::GCHeap*>(gc_reserved_1);
216 }
217
218 inline void set_alloc_heap(SVR::GCHeap* heap)
219 {
220 gc_reserved_1 = heap;
221 }
222
223 inline SVR::GCHeap* get_home_heap()
224 {
225 return static_cast<SVR::GCHeap*>(gc_reserved_2);
226 }
227
228 inline void set_home_heap(SVR::GCHeap* heap)
229 {
230 gc_reserved_2 = heap;
231 }
232#endif // FEATURE_SVR_GC
233};
234
235class IGCHeapInternal : public IGCHeap {
236public:
237
238 virtual ~IGCHeapInternal() {}
239
240private:
241 virtual Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags) = 0;
242public:
243 virtual int GetNumberOfHeaps () = 0;
244 virtual int GetHomeHeapNumber () = 0;
245 virtual size_t GetPromotedBytes(int heap_index) = 0;
246
247 unsigned GetMaxGeneration()
248 {
249 return max_generation;
250 }
251
252 bool IsValidSegmentSize(size_t cbSize)
253 {
254 //Must be aligned on a Mb and greater than 4Mb
255 return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22));
256 }
257
258 bool IsValidGen0MaxSize(size_t cbSize)
259 {
260 return (cbSize >= 64*1024);
261 }
262
263 BOOL IsLargeObject(MethodTable *mt)
264 {
265 return mt->GetBaseSize() >= LARGE_OBJECT_SIZE;
266 }
267
268protected:
269public:
270#if defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP)
271 // Return TRUE if object lives in frozen segment
272 virtual BOOL IsInFrozenSegment (Object * object) = 0;
273#endif // defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP)
274};
275
276// Go through and touch (read) each page straddled by a memory block.
277void TouchPages(void * pStart, size_t cb);
278
279#ifdef WRITE_BARRIER_CHECK
280void updateGCShadow(Object** ptr, Object* val);
281#endif
282
283#ifndef DACCESS_COMPILE
284// The single GC heap instance, shared with the VM.
285extern IGCHeapInternal* g_theGCHeap;
286
287// The single GC handle manager instance, shared with the VM.
288extern IGCHandleManager* g_theGCHandleManager;
289#endif // DACCESS_COMPILE
290
291#ifndef DACCESS_COMPILE
292inline bool IsGCInProgress(bool bConsiderGCStart = false)
293{
294 return g_theGCHeap != nullptr ? g_theGCHeap->IsGCInProgressHelper(bConsiderGCStart) : false;
295}
296#endif // DACCESS_COMPILE
297
298inline bool IsServerHeap()
299{
300#ifdef FEATURE_SVR_GC
301 assert(g_gc_heap_type != GC_HEAP_INVALID);
302 return g_gc_heap_type == GC_HEAP_SVR;
303#else // FEATURE_SVR_GC
304 return false;
305#endif // FEATURE_SVR_GC
306}
307
308#endif // __GC_H
309