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#include "common.h"
6#include "gctoclreventsink.h"
7#include "eventtrace.h"
8
9GCToCLREventSink g_gcToClrEventSink;
10
11void GCToCLREventSink::FireDynamicEvent(const char* eventName, void* payload, uint32_t payloadSize)
12{
13 LIMITED_METHOD_CONTRACT;
14
15 const size_t EventNameMaxSize = 255;
16
17 WCHAR wideEventName[EventNameMaxSize];
18 if (MultiByteToWideChar(CP_ACP, 0, eventName, -1, wideEventName, EventNameMaxSize) == 0)
19 {
20 return;
21 }
22
23 FireEtwGCDynamicEvent(wideEventName, payloadSize, (const BYTE*)payload, GetClrInstanceId());
24}
25
26void GCToCLREventSink::FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type)
27{
28 LIMITED_METHOD_CONTRACT;
29
30 ETW::GCLog::ETW_GC_INFO gcStartInfo;
31 gcStartInfo.GCStart.Count = count;
32 gcStartInfo.GCStart.Depth = depth;
33 gcStartInfo.GCStart.Reason = static_cast<ETW::GCLog::ETW_GC_INFO::GC_REASON>(reason);
34 gcStartInfo.GCStart.Type = static_cast<ETW::GCLog::ETW_GC_INFO::GC_TYPE>(type);
35 ETW::GCLog::FireGcStart(&gcStartInfo);
36}
37
38void GCToCLREventSink::FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength)
39{
40 LIMITED_METHOD_CONTRACT;
41
42 FireEtwGCGenerationRange(generation, rangeStart, rangeUsedLength, rangeReservedLength, GetClrInstanceId());
43}
44
45void GCToCLREventSink::FireGCEnd_V1(uint32_t count, uint32_t depth)
46{
47 LIMITED_METHOD_CONTRACT;
48
49 FireEtwGCEnd_V1(count, depth, GetClrInstanceId());
50}
51
52void GCToCLREventSink::FireGCHeapStats_V1(
53 uint64_t generationSize0,
54 uint64_t totalPromotedSize0,
55 uint64_t generationSize1,
56 uint64_t totalPromotedSize1,
57 uint64_t generationSize2,
58 uint64_t totalPromotedSize2,
59 uint64_t generationSize3,
60 uint64_t totalPromotedSize3,
61 uint64_t finalizationPromotedSize,
62 uint64_t finalizationPromotedCount,
63 uint32_t pinnedObjectCount,
64 uint32_t sinkBlockCount,
65 uint32_t gcHandleCount)
66{
67 LIMITED_METHOD_CONTRACT;
68
69 FireEtwGCHeapStats_V1(generationSize0, totalPromotedSize0, generationSize1, totalPromotedSize1,
70 generationSize2, totalPromotedSize2, generationSize3, totalPromotedSize3,
71 finalizationPromotedSize, finalizationPromotedCount, pinnedObjectCount,
72 sinkBlockCount, gcHandleCount, GetClrInstanceId());
73}
74
75void GCToCLREventSink::FireGCCreateSegment_V1(void* address, size_t size, uint32_t type)
76{
77 LIMITED_METHOD_CONTRACT;
78
79 FireEtwGCCreateSegment_V1((uint64_t)address, static_cast<uint64_t>(size), type, GetClrInstanceId());
80}
81
82void GCToCLREventSink::FireGCFreeSegment_V1(void* address)
83{
84 LIMITED_METHOD_CONTRACT;
85
86 FireEtwGCFreeSegment_V1((uint64_t)address, GetClrInstanceId());
87}
88
89void GCToCLREventSink::FireGCCreateConcurrentThread_V1()
90{
91 LIMITED_METHOD_CONTRACT;
92
93 FireEtwGCCreateConcurrentThread_V1(GetClrInstanceId());
94}
95
96void GCToCLREventSink::FireGCTerminateConcurrentThread_V1()
97{
98 LIMITED_METHOD_CONTRACT;
99
100 FireEtwGCTerminateConcurrentThread_V1(GetClrInstanceId());
101}
102
103void GCToCLREventSink::FireGCTriggered(uint32_t reason)
104{
105 LIMITED_METHOD_CONTRACT;
106
107 FireEtwGCTriggered(reason, GetClrInstanceId());
108}
109
110void GCToCLREventSink::FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes)
111{
112 LIMITED_METHOD_CONTRACT;
113
114 FireEtwGCMarkWithType(heapNum, GetClrInstanceId(), type, bytes);
115}
116
117void GCToCLREventSink::FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId)
118{
119 LIMITED_METHOD_CONTRACT;
120
121 FireEtwGCJoin_V2(heap, joinTime, joinType, GetClrInstanceId(), joinId);
122}
123
124void GCToCLREventSink::FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired,
125 int32_t numHeaps,
126 uint32_t condemnedGeneration,
127 uint32_t gen0reductionCount,
128 uint32_t reason,
129 uint32_t globalMechanisms,
130 uint32_t pauseMode,
131 uint32_t memoryPressure)
132{
133 LIMITED_METHOD_CONTRACT;
134
135 FireEtwGCGlobalHeapHistory_V2(finalYoungestDesired, numHeaps, condemnedGeneration, gen0reductionCount, reason,
136 globalMechanisms, GetClrInstanceId(), pauseMode, memoryPressure);
137}
138
139void GCToCLREventSink::FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind)
140{
141 LIMITED_METHOD_CONTRACT;
142
143 FireEtwGCAllocationTick_V1(allocationAmount, allocationKind, GetClrInstanceId());
144}
145
146void GCToCLREventSink::FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress)
147{
148 LIMITED_METHOD_CONTRACT;
149
150 void * typeId = nullptr;
151 const WCHAR * name = nullptr;
152 InlineSString<MAX_CLASSNAME_LENGTH> strTypeName;
153 EX_TRY
154 {
155 TypeHandle th = GetThread()->GetTHAllocContextObj();
156
157 if (th != 0)
158 {
159 th.GetName(strTypeName);
160 name = strTypeName.GetUnicode();
161 typeId = th.GetMethodTable();
162 }
163 }
164 EX_CATCH {}
165 EX_END_CATCH(SwallowAllExceptions)
166
167 if (typeId != nullptr)
168 {
169 FireEtwGCAllocationTick_V3(static_cast<uint32_t>(allocationAmount),
170 allocationKind,
171 GetClrInstanceId(),
172 allocationAmount,
173 typeId,
174 name,
175 heapIndex,
176 objectAddress);
177 }
178}
179
180void GCToCLREventSink::FirePinObjectAtGCTime(void* object, uint8_t** ppObject)
181{
182 LIMITED_METHOD_CONTRACT;
183
184 Object* obj = (Object*)object;
185
186 InlineSString<MAX_CLASSNAME_LENGTH> strTypeName;
187
188 EX_TRY
189 {
190 FAULT_NOT_FATAL();
191
192 TypeHandle th = obj->GetGCSafeTypeHandleIfPossible();
193 if(th != NULL)
194 {
195 th.GetName(strTypeName);
196 }
197
198 FireEtwPinObjectAtGCTime(ppObject,
199 object,
200 obj->GetSize(),
201 strTypeName.GetUnicode(),
202 GetClrInstanceId());
203 }
204 EX_CATCH {}
205 EX_END_CATCH(SwallowAllExceptions)
206}
207
208void GCToCLREventSink::FirePinPlugAtGCTime(uint8_t* plugStart, uint8_t* plugEnd, uint8_t* gapBeforeSize)
209{
210 LIMITED_METHOD_CONTRACT;
211 FireEtwPinPlugAtGCTime(plugStart, plugEnd, gapBeforeSize, GetClrInstanceId());
212}
213
214void GCToCLREventSink::FireGCPerHeapHistory_V3(void *freeListAllocated,
215 void *freeListRejected,
216 void *endOfSegAllocated,
217 void *condemnedAllocated,
218 void *pinnedAllocated,
219 void *pinnedAllocatedAdvance,
220 uint32_t runningFreeListEfficiency,
221 uint32_t condemnReasons0,
222 uint32_t condemnReasons1,
223 uint32_t compactMechanisms,
224 uint32_t expandMechanisms,
225 uint32_t heapIndex,
226 void *extraGen0Commit,
227 uint32_t count,
228 uint32_t valuesLen,
229 void *values)
230{
231 FireEtwGCPerHeapHistory_V3(GetClrInstanceId(),
232 freeListAllocated,
233 freeListRejected,
234 endOfSegAllocated,
235 condemnedAllocated,
236 pinnedAllocated,
237 pinnedAllocatedAdvance,
238 runningFreeListEfficiency,
239 condemnReasons0,
240 condemnReasons1,
241 compactMechanisms,
242 expandMechanisms,
243 heapIndex,
244 extraGen0Commit,
245 count,
246 valuesLen,
247 values);
248}
249
250
251
252void GCToCLREventSink::FireBGCBegin()
253{
254 FireEtwBGCBegin(GetClrInstanceId());
255}
256
257void GCToCLREventSink::FireBGC1stNonConEnd()
258{
259 FireEtwBGC1stNonConEnd(GetClrInstanceId());
260}
261
262void GCToCLREventSink::FireBGC1stConEnd()
263{
264 FireEtwBGC1stConEnd(GetClrInstanceId());
265}
266
267void GCToCLREventSink::FireBGC1stSweepEnd(uint32_t genNumber)
268{
269 FireEtwBGC1stSweepEnd(genNumber, GetClrInstanceId());
270}
271
272void GCToCLREventSink::FireBGC2ndNonConBegin()
273{
274 FireEtwBGC2ndNonConBegin(GetClrInstanceId());
275}
276
277void GCToCLREventSink::FireBGC2ndNonConEnd()
278{
279 FireEtwBGC2ndNonConEnd(GetClrInstanceId());
280}
281
282void GCToCLREventSink::FireBGC2ndConBegin()
283{
284 FireEtwBGC2ndConBegin(GetClrInstanceId());
285}
286
287void GCToCLREventSink::FireBGC2ndConEnd()
288{
289 FireEtwBGC2ndConEnd(GetClrInstanceId());
290}
291
292void GCToCLREventSink::FireBGCDrainMark(uint64_t objects)
293{
294 FireEtwBGCDrainMark(objects, GetClrInstanceId());
295}
296
297void GCToCLREventSink::FireBGCRevisit(uint64_t pages, uint64_t objects, uint32_t isLarge)
298{
299 FireEtwBGCRevisit(pages, objects, isLarge, GetClrInstanceId());
300}
301
302void GCToCLREventSink::FireBGCOverflow(uint64_t min, uint64_t max, uint64_t objects, uint32_t isLarge)
303{
304 FireEtwBGCOverflow(min, max, objects, isLarge, GetClrInstanceId());
305}
306
307void GCToCLREventSink::FireBGCAllocWaitBegin(uint32_t reason)
308{
309 FireEtwBGCAllocWaitBegin(reason, GetClrInstanceId());
310}
311
312void GCToCLREventSink::FireBGCAllocWaitEnd(uint32_t reason)
313{
314 FireEtwBGCAllocWaitEnd(reason, GetClrInstanceId());
315}
316
317void GCToCLREventSink::FireGCFullNotify_V1(uint32_t genNumber, uint32_t isAlloc)
318{
319 FireEtwGCFullNotify_V1(genNumber, isAlloc, GetClrInstanceId());
320}
321
322void GCToCLREventSink::FireSetGCHandle(void *handleID, void *objectID, uint32_t kind, uint32_t generation, uint64_t appDomainID)
323{
324 FireEtwSetGCHandle(handleID, objectID, kind, generation, appDomainID, GetClrInstanceId());
325}
326
327void GCToCLREventSink::FirePrvSetGCHandle(void *handleID, void *objectID, uint32_t kind, uint32_t generation, uint64_t appDomainID)
328{
329 FireEtwPrvSetGCHandle(handleID, objectID, kind, generation, appDomainID, GetClrInstanceId());
330}
331
332void GCToCLREventSink::FireDestroyGCHandle(void *handleID)
333{
334 FireEtwDestroyGCHandle(handleID, GetClrInstanceId());
335}
336
337void GCToCLREventSink::FirePrvDestroyGCHandle(void *handleID)
338{
339 FireEtwPrvDestroyGCHandle(handleID, GetClrInstanceId());
340}
341