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.
5 #ifndef _GCINTERFACE_EE_H_
6 #define _GCINTERFACE_EE_H_
10 kEtwGCRootFlagsPinning = 0x1,
11 kEtwGCRootFlagsWeakRef = 0x2,
12 kEtwGCRootFlagsInterior = 0x4,
13 kEtwGCRootFlagsRefCounted = 0x8,
18 kEtwGCRootKindStack = 0,
19 kEtwGCRootKindFinalizer = 1,
20 kEtwGCRootKindHandle = 2,
21 kEtwGCRootKindOther = 3,
24 // This interface provides functions that the GC can use to fire events.
25 // Events fired on this interface are split into two categories: "known"
26 // events and "dynamic" events. Known events are events that are baked-in
27 // to the hosting runtime's event manifest and are part of the GC/EE interface.
28 // There is one callback on IGCToCLREventSink for each known event.
30 // Dynamic events are constructed at runtime by the GC and are not known
31 // to the EE. ([LOCALGC TODO dynamic event implementation])
32 class IGCToCLREventSink
35 // Fires a dynamic event with the given event name and payload. Dynamic
36 // events are not known to the EE and are fired as an unschematized event
37 // to the underlying eventing implementation.
39 void FireDynamicEvent(
40 const char* eventName,
42 uint32_t payloadSize) = 0;
44 void FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type) = 0;
47 void FireGCEnd_V1(uint32_t count, uint32_t depth) = 0;
50 void FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength) = 0;
53 void FireGCHeapStats_V1(
54 uint64_t generationSize0,
55 uint64_t totalPromotedSize0,
56 uint64_t generationSize1,
57 uint64_t totalPromotedSize1,
58 uint64_t generationSize2,
59 uint64_t totalPromotedSize2,
60 uint64_t generationSize3,
61 uint64_t totalPromotedSize3,
62 uint64_t finalizationPromotedSize,
63 uint64_t finalizationPromotedCount,
64 uint32_t pinnedObjectCount,
65 uint32_t sinkBlockCount,
66 uint32_t gcHandleCount) = 0;
69 void FireGCCreateSegment_V1(void* address, size_t size, uint32_t type) = 0;
72 void FireGCFreeSegment_V1(void* address) = 0;
75 void FireGCCreateConcurrentThread_V1() = 0;
78 void FireGCTerminateConcurrentThread_V1() = 0;
81 void FireGCTriggered(uint32_t reason) = 0;
84 void FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes) = 0;
87 void FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId) = 0;
90 void FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired,
92 uint32_t condemnedGeneration,
93 uint32_t gen0reductionCount,
95 uint32_t globalMechanisms,
97 uint32_t memoryPressure) = 0;
100 void FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind) = 0;
103 void FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress) = 0;
106 void FirePinObjectAtGCTime(void* object, uint8_t** ppObject) = 0;
109 void FireGCPerHeapHistory_V3(void *freeListAllocated,
110 void *freeListRejected,
111 void *endOfSegAllocated,
112 void *condemnedAllocated,
113 void *pinnedAllocated,
114 void *pinnedAllocatedAdvance,
115 uint32_t runningFreeListEfficiency,
116 uint32_t condemnReasons0,
117 uint32_t condemnReasons1,
118 uint32_t compactMechanisms,
119 uint32_t expandMechanisms,
121 void *extraGen0Commit,
126 void FireBGCBegin() = 0;
128 void FireBGC1stNonConEnd() = 0;
130 void FireBGC1stConEnd() = 0;
132 void FireBGC2ndNonConBegin() = 0;
134 void FireBGC2ndNonConEnd() = 0;
136 void FireBGC2ndConBegin() = 0;
138 void FireBGC2ndConEnd() = 0;
140 void FireBGCDrainMark(uint64_t objects) = 0;
142 void FireBGCRevisit(uint64_t pages, uint64_t objects, uint32_t isLarge) = 0;
144 void FireBGCOverflow(uint64_t min, uint64_t max, uint64_t objects, uint32_t isLarge) = 0;
146 void FireBGCAllocWaitBegin(uint32_t reason) = 0;
148 void FireBGCAllocWaitEnd(uint32_t reason) = 0;
150 void FireGCFullNotify_V1(uint32_t genNumber, uint32_t isAlloc) = 0;
152 void FireSetGCHandle(void *handleID, void *objectID, uint32_t kind, uint32_t generation, uint64_t appDomainID) = 0;
154 void FirePrvSetGCHandle(void *handleID, void *objectID, uint32_t kind, uint32_t generation, uint64_t appDomainID) = 0;
156 void FireDestroyGCHandle(void *handleID) = 0;
158 void FirePrvDestroyGCHandle(void *handleID) = 0;
161 // This interface provides the interface that the GC will use to speak to the rest
162 // of the execution engine. Everything that the GC does that requires the EE
163 // to be informed or that requires EE action must go through this interface.
165 // When BUILD_AS_STANDALONE is defined, this class is named IGCToCLR and is
166 // an abstract class. The EE will provide a class that fulfills this interface,
167 // and the GC will dispatch virtually on it to call into the EE. When BUILD_AS_STANDALONE
168 // is not defined, this class is named GCToEEInterface and the GC will dispatch statically on it.
171 // Suspends the EE for the given reason.
173 void SuspendEE(SUSPEND_REASON reason) = 0;
175 // Resumes all paused threads, with a boolean indicating
176 // if the EE is being restarted because a GC is complete.
178 void RestartEE(bool bFinishedGC) = 0;
180 // Performs a stack walk of all managed threads and invokes the given promote_func
181 // on all GC roots encountered on the stack. Depending on the condemned generation,
182 // this function may also enumerate all static GC refs if necessary.
184 void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) = 0;
186 // Callback from the GC informing the EE that it is preparing to start working.
188 void GcStartWork(int condemned, int max_gen) = 0;
190 // Callback from the GC informing the EE that it has completed the managed stack
191 // scan. User threads are still suspended at this point.
193 void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) = 0;
195 // Callback from the GC informing the EE that the background sweep phase of a BGC is
198 void GcBeforeBGCSweepWork() = 0;
200 // Callback from the GC informing the EE that a GC has completed.
202 void GcDone(int condemned) = 0;
204 // Predicate for the GC to query whether or not a given refcounted handle should
207 bool RefCountedHandleCallbacks(Object * pObject) = 0;
209 // Performs a weak pointer scan of the sync block cache.
211 void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2) = 0;
213 // Indicates to the EE that the GC intends to demote objects in the sync block cache.
215 void SyncBlockCacheDemote(int max_gen) = 0;
217 // Indicates to the EE that the GC has granted promotion to objects in the sync block cache.
219 void SyncBlockCachePromotionsGranted(int max_gen) = 0;
222 uint32_t GetActiveSyncBlockCount() = 0;
224 // Queries whether or not the current thread has preemptive GC disabled.
226 bool IsPreemptiveGCDisabled() = 0;
228 // Enables preemptive GC on the current thread. Returns true if the thread mode
229 // was changed and false if the thread mode wasn't changed or the thread is not
232 bool EnablePreemptiveGC() = 0;
234 // Disables preemptive GC on the current thread.
236 void DisablePreemptiveGC() = 0;
238 // Gets the Thread instance for the current thread, or null if no thread
239 // instance is associated with this thread.
241 // If the GC created the current thread, GetThread returns null for threads
242 // that were not created as suspendable (see `IGCHeap::CreateThread`).
244 Thread* GetThread() = 0;
246 // Retrieves the alloc context associated with the current thread.
248 gc_alloc_context * GetAllocContext() = 0;
250 // Calls the given enum_alloc_context_func with every active alloc context.
252 void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param) = 0;
254 // Creates and returns a new thread.
256 // threadStart - The function that will serve as the thread stub for the
257 // new thread. It will be invoked immediately upon the
258 // new thread upon creation.
259 // arg - The argument that will be passed verbatim to threadStart.
260 // is_suspendable - Whether or not the thread that is created should be suspendable
261 // from a runtime perspective. Threads that are suspendable have
262 // a VM Thread object associated with them that can be accessed
263 // using `IGCHeap::GetThread`.
264 // name - The name of this thread, optionally used for diagnostic purposes.
266 // true if the thread was started successfully, false if not.
268 bool CreateThread(void (*threadStart)(void*), void* arg, bool is_suspendable, const char* name) = 0;
270 // When a GC starts, gives the diagnostics code a chance to run.
272 void DiagGCStart(int gen, bool isInduced) = 0;
274 // When GC heap segments change, gives the diagnostics code a chance to run.
276 void DiagUpdateGenerationBounds() = 0;
278 // When a GC ends, gives the diagnostics code a chance to run.
280 void DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent) = 0;
282 // During a GC after we discover what objects' finalizers should run, gives the diagnostics code a chance to run.
284 void DiagWalkFReachableObjects(void* gcContext) = 0;
286 // During a GC after we discover the survivors and the relocation info,
287 // gives the diagnostics code a chance to run. This includes LOH if we are
290 void DiagWalkSurvivors(void* gcContext) = 0;
292 // During a full GC after we discover what objects to survive on LOH,
293 // gives the diagnostics code a chance to run.
295 void DiagWalkLOHSurvivors(void* gcContext) = 0;
297 // At the end of a background GC, gives the diagnostics code a chance to run.
299 void DiagWalkBGCSurvivors(void* gcContext) = 0;
301 // Informs the EE of changes to the location of the card table, potentially updating the write
302 // barrier if it needs to be updated.
304 void StompWriteBarrier(WriteBarrierParameters* args) = 0;
306 // Signals to the finalizer thread that there are objects ready to
309 void EnableFinalization(bool foundFinalizers) = 0;
311 // Signals to the EE that the GC encountered a fatal error and can't recover.
313 void HandleFatalError(unsigned int exitCode) = 0;
315 // Asks the EE if it wants a particular object to be finalized when unloading
318 bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj) = 0;
320 // Offers the EE the option to finalize the given object eagerly, i.e.
321 // not on the finalizer thread but on the current thread. The
322 // EE returns true if it finalized the object eagerly and the GC does not
323 // need to do so, and false if it chose not to eagerly finalize the object
324 // and it's up to the GC to finalize it later.
326 bool EagerFinalized(Object* obj) = 0;
328 // Asks the EE if it wishes for the current GC to be a blocking GC. The GC will
329 // only invoke this callback when it intends to do a full GC, so at this point
330 // the EE can opt to elevate that collection to be a blocking GC and not a background one.
332 bool ForceFullGCToBeBlocking() = 0;
334 // Retrieves the method table for the free object, a special kind of object used by the GC
335 // to keep the heap traversable. Conceptually, the free object is similar to a managed array
336 // of bytes: it consists of an object header (like all objects) and a "numComponents" field,
337 // followed by some number of bytes of space that's free on the heap.
339 // The free object allows the GC to traverse the heap because it can inspect the numComponents
340 // field to see how many bytes to skip before the next object on a heap segment begins.
342 MethodTable* GetFreeObjectMethodTable() = 0;
344 // Asks the EE for the value of a given configuration key. If the EE does not know or does not
345 // have a value for the requeested config key, false is returned and the value of the passed-in
346 // pointer is undefined. Otherwise, true is returned and the config key's value is written to
347 // the passed-in pointer.
349 bool GetBooleanConfigValue(const char* key, bool* value) = 0;
352 bool GetIntConfigValue(const char* key, int64_t* value) = 0;
355 bool GetStringConfigValue(const char* key, const char** value) = 0;
358 void FreeStringConfigValue(const char* value) = 0;
360 // Returns true if this thread is a "GC thread", or a thread capable of
361 // doing GC work. Threads are either /always/ GC threads
362 // (if they were created for this purpose - background GC threads
363 // and server GC threads) or they became GC threads by suspending the EE
364 // and initiating a collection.
366 bool IsGCThread() = 0;
368 // Returns true if the current thread is either a background GC thread
369 // or a server GC thread.
371 bool WasCurrentThreadCreatedByGC() = 0;
373 // Given an object, if this object is an instance of `System.Threading.OverlappedData`,
374 // and the runtime treats instances of this class specially, traverses the objects that
375 // are directly or (once) indirectly pinned by this object and reports them to the GC for
376 // the purposes of relocation and promotion.
378 // Overlapped objects are very special and as such the objects they wrap can't be promoted in
379 // the same manner as normal objects. This callback gives the EE the opportunity to hide these
380 // details, if they are implemented at all.
382 // This function is a no-op if "object" is not an OverlappedData object.
384 void WalkAsyncPinnedForPromotion(Object* object, ScanContext* sc, promote_func* callback) = 0;
386 // Given an object, if this object is an instance of `System.Threading.OverlappedData` and the
387 // runtime treats instances of this class specially, traverses the objects that are directly
388 // or once indirectly pinned by this object and invokes the given callback on them. The callback
389 // is passed the following arguments:
390 // Object* "from" - The object that "caused" the "to" object to be pinned. If a single object
391 // is pinned directly by this OverlappedData, this object will be the
392 // OverlappedData object itself. If an array is pinned by this OverlappedData,
393 // this object will be the pinned array.
394 // Object* "to" - The object that is pinned by the "from" object. If a single object is pinned
395 // by an OverlappedData, "to" will be that single object. If an array is pinned
396 // by an OverlappedData, the callback will be invoked on all elements of that
397 // array and each element will be a "to" object.
398 // void* "context" - Passed verbatim from "WalkOverlappedObject" to the callback function.
399 // The "context" argument will be passed directly to the callback without modification or inspection.
401 // This function is a no-op if "object" is not an OverlappedData object.
403 void WalkAsyncPinned(Object* object, void* context, void(*callback)(Object*, Object*, void*)) = 0;
405 // Returns an IGCToCLREventSink instance that can be used to fire events.
407 IGCToCLREventSink* EventSink() = 0;
410 #endif // _GCINTERFACE_EE_H_