1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-08 03:27:04 +09:00
Satori/src/coreclr/gc/gcimpl.h
2025-05-13 11:24:44 -07:00

338 lines
11 KiB
C

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#ifndef GCIMPL_H_
#define GCIMPL_H_
#ifdef SERVER_GC
#define MULTIPLE_HEAPS 1
#endif // SERVER_GC
#ifdef MULTIPLE_HEAPS
#define PER_HEAP
#else //MULTIPLE_HEAPS
#define PER_HEAP static
#endif // MULTIPLE_HEAPS
#define PER_HEAP_ISOLATED static
#if defined(WRITE_BARRIER_CHECK) && !defined (MULTIPLE_HEAPS)
void initGCShadow();
void deleteGCShadow();
void checkGCWriteBarrier();
#else
inline void initGCShadow() {}
inline void deleteGCShadow() {}
inline void checkGCWriteBarrier() {}
#endif
void GCProfileWalkHeap(bool etwOnly);
class gc_heap;
class CFinalize;
extern bool g_fFinalizerRunOnShutDown;
extern bool g_built_with_svr_gc;
extern uint8_t g_build_variant;
extern VOLATILE(int32_t) g_no_gc_lock;
class GCHeap : public IGCHeapInternal
{
protected:
#ifdef MULTIPLE_HEAPS
gc_heap* pGenGCHeap;
#else
#define pGenGCHeap ((gc_heap*)0)
#endif //MULTIPLE_HEAPS
friend class CFinalize;
friend class gc_heap;
friend struct ::alloc_context;
friend void EnterAllocLock();
friend void LeaveAllocLock();
friend void ProfScanRootsHelper(Object** object, ScanContext *pSC, uint32_t dwFlags);
friend void GCProfileWalkHeap(bool etwOnly);
public:
//In order to keep gc.cpp cleaner, ugly EE specific code is relegated to methods.
static void UpdatePreGCCounters();
static void UpdatePostGCCounters();
public:
GCHeap(){};
/* BaseGCHeap Methods*/
PER_HEAP_ISOLATED HRESULT StaticShutdown ();
size_t GetTotalBytesInUse ();
// Gets the amount of bytes objects currently occupy on the GC heap.
size_t GetCurrentObjSize();
uint64_t GetTotalAllocatedBytes();
size_t GetLastGCStartTime(int generation);
size_t GetLastGCDuration(int generation);
size_t GetNow();
void DiagTraceGCSegments ();
void PublishObject(uint8_t* obj);
bool IsGCInProgressHelper (bool bConsiderGCStart = false);
uint32_t WaitUntilGCComplete (bool bConsiderGCStart = false);
void SetGCInProgress(bool fInProgress);
bool RuntimeStructuresValid();
void SetSuspensionPending(bool fSuspensionPending);
void SetYieldProcessorScalingFactor(float yieldProcessorScalingFactor);
void SetWaitForGCEvent();
void ResetWaitForGCEvent();
HRESULT Initialize ();
Object* Alloc (gc_alloc_context* acontext, size_t size, uint32_t flags);
void FixAllocContext (gc_alloc_context* acontext, void* arg, void *heap);
Object* GetContainingObject(void *pInteriorPtr, bool fCollectedGenOnly);
#ifdef MULTIPLE_HEAPS
static void AssignHeap (alloc_context* acontext);
static GCHeap* GetHeap (int);
#endif //MULTIPLE_HEAPS
int GetHomeHeapNumber ();
bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number);
int GetNumberOfHeaps ();
void HideAllocContext(alloc_context*);
void RevealAllocContext(alloc_context*);
bool IsLargeObject(Object *pObj);
HRESULT GarbageCollect (int generation = -1, bool low_memory_p=false, int mode=collection_blocking);
////
// GC callback functions
// Check if an argument is promoted (ONLY CALL DURING
// THE PROMOTIONSGRANTED CALLBACK.)
bool IsPromoted (Object *object);
size_t GetPromotedBytes (int heap_index);
int CollectionCount (int generation, int get_bgc_fgc_count = 0);
// promote an object
PER_HEAP_ISOLATED void Promote (Object** object,
ScanContext* sc,
uint32_t flags=0);
// Find the relocation address for an object
PER_HEAP_ISOLATED void Relocate (Object** object,
ScanContext* sc,
uint32_t flags=0);
HRESULT Init (size_t heapSize);
//Register an object for finalization
bool RegisterForFinalization (int gen, Object* obj);
//Unregister an object for finalization
void SetFinalizationRun (Object* obj);
// returns the generation number of an object (not valid during relocation) or
// INT32_MAX if the object belongs to a non-GC heap.
unsigned WhichGeneration (Object* object);
// returns TRUE is the object is ephemeral
bool IsEphemeral (Object* object);
bool IsHeapPointer (void* object, bool small_heap_only = false);
void ValidateObjectMember (Object *obj);
PER_HEAP size_t ApproxTotalBytesInUse(BOOL small_heap_only = FALSE);
unsigned GetCondemnedGeneration();
void GetMemoryInfo(uint64_t* highMemLoadThresholdBytes,
uint64_t* totalAvailableMemoryBytes,
uint64_t* lastRecordedMemLoadBytes,
uint64_t* lastRecordedHeapSizeBytes,
uint64_t* lastRecordedFragmentationBytes,
uint64_t* totalCommittedBytes,
uint64_t* promotedBytes,
uint64_t* pinnedObjectCount,
uint64_t* finalizationPendingCount,
uint64_t* index,
uint32_t* generation,
uint32_t* pauseTimePct,
bool* isCompaction,
bool* isConcurrent,
uint64_t* genInfoRaw,
uint64_t* pauseInfoRaw,
int kind);
int64_t GetTotalPauseDuration();
void EnumerateConfigurationValues(void* context, ConfigurationValueFunc configurationValueFunc);
uint32_t GetMemoryLoad();
int GetGcLatencyMode();
int SetGcLatencyMode(int newLatencyMode);
int GetLOHCompactionMode();
void SetLOHCompactionMode(int newLOHCompactionyMode);
bool RegisterForFullGCNotification(uint32_t gen2Percentage,
uint32_t lohPercentage);
bool CancelFullGCNotification();
int WaitForFullGCApproach(int millisecondsTimeout);
int WaitForFullGCComplete(int millisecondsTimeout);
int StartNoGCRegion(uint64_t totalSize, bool lohSizeKnown, uint64_t lohSize, bool disallowFullBlockingGC);
int EndNoGCRegion();
enable_no_gc_region_callback_status EnableNoGCRegionCallback(NoGCRegionCallbackFinalizerWorkItem* callback, uint64_t callback_threshold);
FinalizerWorkItem* GetExtraWorkForFinalization();
uint64_t GetGenerationBudget(int generation);
size_t GetLOHThreshold();
unsigned GetGcCount();
Object* GetNextFinalizable() { return GetNextFinalizableObject(); };
size_t GetNumberOfFinalizable() { return GetNumberFinalizableObjects(); }
size_t GetValidSegmentSize(bool large_seg = false);
void SetReservedVMLimit (size_t vmlimit);
PER_HEAP_ISOLATED Object* GetNextFinalizableObject();
PER_HEAP_ISOLATED size_t GetNumberFinalizableObjects();
PER_HEAP_ISOLATED size_t GetFinalizablePromotedCount();
void DiagWalkObject (Object* obj, walk_fn fn, void* context);
void DiagWalkObject2 (Object* obj, walk_fn2 fn, void* context);
public: // FIX
// Lock for finalization
PER_HEAP_ISOLATED
VOLATILE(int32_t) m_GCFLock;
PER_HEAP_ISOLATED BOOL GcCollectClasses;
PER_HEAP_ISOLATED
VOLATILE(BOOL) GcInProgress; // used for syncing w/GC
PER_HEAP_ISOLATED VOLATILE(unsigned) GcCount;
PER_HEAP_ISOLATED unsigned GcCondemnedGeneration;
// calculated at the end of a GC.
PER_HEAP_ISOLATED size_t totalSurvivedSize;
// Use only for GC tracing.
PER_HEAP uint64_t GcDuration;
size_t GarbageCollectGeneration (unsigned int gen=0, gc_reason reason=reason_empty);
// Interface with gc_heap
size_t GarbageCollectTry (int generation, BOOL low_memory_p=FALSE, int mode=collection_blocking);
// frozen segment management functions
virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo);
virtual void UnregisterFrozenSegment(segment_handle seg);
virtual bool IsInFrozenSegment(Object *object);
virtual void UpdateFrozenSegment(segment_handle seg, uint8_t* allocated, uint8_t* committed);
// Event control functions
void ControlEvents(GCEventKeyword keyword, GCEventLevel level);
void ControlPrivateEvents(GCEventKeyword keyword, GCEventLevel level);
void WaitUntilConcurrentGCComplete (); // Use in managd threads
#ifndef DACCESS_COMPILE
HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout); // Use in native threads. TRUE if succeed. FALSE if failed or timeout
#endif
bool IsConcurrentGCInProgress();
// Enable/disable concurrent GC
void TemporaryEnableConcurrentGC();
void TemporaryDisableConcurrentGC();
bool IsConcurrentGCEnabled();
PER_HEAP_ISOLATED GCEvent *WaitForGCEvent; // used for syncing w/GC
PER_HEAP_ISOLATED CFinalize* m_Finalize;
PER_HEAP_ISOLATED gc_heap* Getgc_heap();
private:
static bool SafeToRestartManagedThreads()
{
// Note: this routine should return true when the last barrier
// to threads returning to cooperative mode is down after gc.
// In other words, if the sequence in GCHeap::RestartEE changes,
// the condition here may have to change as well.
return g_fSuspensionPending == 0;
}
public:
//return TRUE if GC actually happens, otherwise FALSE
bool StressHeap(gc_alloc_context * acontext);
#ifndef FEATURE_NATIVEAOT // Redhawk forces relocation a different way
#ifdef STRESS_HEAP
protected:
// only used in BACKGROUND_GC, but the symbol is not defined yet...
PER_HEAP_ISOLATED int gc_stress_fgcs_in_bgc;
#if !defined(MULTIPLE_HEAPS)
// handles to hold the string objects that will force GC movement
enum { NUM_HEAP_STRESS_OBJS = 8 };
PER_HEAP OBJECTHANDLE m_StressObjs[NUM_HEAP_STRESS_OBJS];
PER_HEAP int m_CurStressObj;
#endif // !defined(MULTIPLE_HEAPS)
#endif // STRESS_HEAP
#endif // FEATURE_NATIVEAOT
virtual void DiagDescrGenerations (gen_walk_fn fn, void *context);
virtual void DiagWalkSurvivorsWithType (void* gc_context, record_surv_fn fn, void* diag_context, walk_surv_type type, int gen_number=-1);
virtual void DiagWalkFinalizeQueue (void* gc_context, fq_walk_fn fn);
virtual void DiagScanFinalizeQueue (fq_scan_fn fn, ScanContext* context);
virtual void DiagScanHandles (handle_scan_fn fn, int gen_number, ScanContext* context);
virtual void DiagScanDependentHandles (handle_scan_fn fn, int gen_number, ScanContext* context);
virtual void DiagWalkHeap(walk_fn fn, void* context, int gen_number, bool walk_large_object_heap_p);
virtual void DiagGetGCSettings(EtwGCSettingsInfo* etw_settings);
virtual unsigned int GetGenerationWithRange(Object* object, uint8_t** ppStart, uint8_t** ppAllocated, uint8_t** ppReserved);
virtual void DiagWalkHeapWithACHandling(walk_fn fn, void* context, int gen_number, bool walk_large_object_heap_p);
public:
Object * NextObj (Object * object);
int GetLastGCPercentTimeInGC();
size_t GetLastGCGenerationSize(int gen);
virtual void Shutdown();
static void ReportGenerationBounds();
virtual int RefreshMemoryLimit();
// Inherited via IGCHeapInternal
virtual void BulkMoveWithWriteBarrier(void* dst, const void* src, size_t byteCount);
};
#endif // GCIMPL_H_