[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / eventpipeblock.cpp
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 "eventpipeblock.h"
7 #include "eventpipeeventinstance.h"
8 #include "fastserializableobject.h"
9 #include "fastserializer.h"
10
11 // my attempts to include limits.h were hitting missing headers on Linux
12 // This might be resolvable with more effort but I chose not to head
13 // down the rabbit hole when a perfectly decent 60 second fix was available:
14 #ifndef LLONG_MIN
15 #define LLONG_MIN 0x8000000000000000
16 #endif
17 #ifndef LLONG_MAX 
18 #define LLONG_MAX 0x7FFFFFFFFFFFFFFF
19 #endif
20
21 #ifdef FEATURE_PERFTRACING
22
23
24
25 DWORD GetBlockVersion(EventPipeSerializationFormat format)
26 {
27     LIMITED_METHOD_CONTRACT;
28     switch (format)
29     {
30     case EventPipeSerializationFormat::NetPerfV3:
31         return 1;
32     case EventPipeSerializationFormat::NetTraceV4:
33         return 2;
34     default:
35         _ASSERTE(!"Unrecognized EventPipeSerializationFormat");
36         return 0;
37     }
38 }
39
40 DWORD GetBlockMinVersion(EventPipeSerializationFormat format)
41 {
42     LIMITED_METHOD_CONTRACT;
43     switch (format)
44     {
45     case EventPipeSerializationFormat::NetPerfV3:
46         return 0;
47     case EventPipeSerializationFormat::NetTraceV4:
48         return 2;
49     default:
50         _ASSERTE(!"Unrecognized EventPipeSerializationFormat");
51         return 0;
52     }
53 }
54
55 EventPipeBlock::EventPipeBlock(unsigned int maxBlockSize, EventPipeSerializationFormat format) :
56     FastSerializableObject(GetBlockVersion(format), GetBlockMinVersion(format), format >= EventPipeSerializationFormat::NetTraceV4)
57 {
58     CONTRACTL
59     {
60         NOTHROW;
61         GC_NOTRIGGER;
62         MODE_ANY;
63     }
64     CONTRACTL_END;
65
66     m_pBlock = new (nothrow) BYTE[maxBlockSize];
67     if (m_pBlock == NULL)
68     {
69         return;
70     }
71
72     memset(m_pBlock, 0, maxBlockSize);
73     m_pWritePointer = m_pBlock;
74     m_pEndOfTheBuffer = m_pBlock + maxBlockSize;
75     m_format = format;
76 }
77
78 EventPipeBlock::~EventPipeBlock()
79 {
80     CONTRACTL
81     {
82         NOTHROW;
83         GC_NOTRIGGER;
84         MODE_ANY;
85     }
86     CONTRACTL_END;
87
88     delete[] m_pBlock;
89 }
90
91 void EventPipeBlock::Clear()
92 {
93     CONTRACTL
94     {
95         NOTHROW;
96         GC_NOTRIGGER;
97         MODE_ANY;
98     }
99     CONTRACTL_END;
100
101     if (m_pBlock == NULL)
102     {
103         return;
104     }
105
106     _ASSERTE(m_pWritePointer <= m_pEndOfTheBuffer);
107
108     memset(m_pBlock, 0, GetSize());
109     m_pWritePointer = m_pBlock;
110 }
111
112 EventPipeEventBlockBase::EventPipeEventBlockBase(unsigned int maxBlockSize, EventPipeSerializationFormat format, bool fUseHeaderCompression) :
113     EventPipeBlock(maxBlockSize, format), m_fUseHeaderCompression(fUseHeaderCompression)
114 {
115     memset(m_compressedHeader, 0, 100);
116     Clear();
117 }
118
119 void EventPipeEventBlockBase::Clear()
120 {
121     EventPipeBlock::Clear();
122     m_lastHeader.MetadataId = 0;
123     m_lastHeader.SequenceNumber = 0;
124     m_lastHeader.ThreadId = 0;
125     m_lastHeader.CaptureThreadId = 0;
126     m_lastHeader.StackId = 0;
127     m_lastHeader.TimeStamp.QuadPart = 0;
128     m_lastHeader.ActivityId = { 0 };
129     m_lastHeader.RelatedActivityId = { 0 };
130     m_lastHeader.DataLength = 0;
131
132     m_minTimeStamp.QuadPart = LLONG_MAX;
133     m_maxTimeStamp.QuadPart = LLONG_MIN;
134 }
135
136 void WriteVarUInt32(BYTE* & pWritePointer, unsigned int value)
137 {
138     while (value >= 0x80)
139     {
140         *pWritePointer = (BYTE)(value | 0x80);
141         pWritePointer++;
142         value >>= 7;
143     }
144     *pWritePointer = (BYTE)value;
145     pWritePointer++;
146 }
147
148 void WriteVarUInt64(BYTE* & pWritePointer, ULONGLONG value)
149 {
150     while (value >= 0x80)
151     {
152         *pWritePointer = (BYTE)(value | 0x80);
153         pWritePointer++;
154         value >>= 7;
155     }
156     *pWritePointer = (BYTE)value;
157     pWritePointer++;
158 }
159
160 bool EventPipeEventBlockBase::WriteEvent(EventPipeEventInstance &instance, 
161                                          ULONGLONG captureThreadId,
162                                          unsigned int sequenceNumber,
163                                          DWORD stackId,
164                                          BOOL isSortedEvent)
165 {
166     CONTRACTL
167     {
168         NOTHROW;
169         GC_NOTRIGGER;
170         MODE_ANY;
171         PRECONDITION(isSortedEvent || m_format >= EventPipeSerializationFormat::NetTraceV4);
172     }
173     CONTRACTL_END;
174
175     if (m_pBlock == NULL)
176     {
177         return false;
178     }
179
180     unsigned int dataLength = 0;
181     BYTE* alignedEnd = NULL;
182     unsigned int captureProcNumber = instance.GetProcNumber();
183
184     if (!m_fUseHeaderCompression)
185     {
186         unsigned int totalSize = instance.GetAlignedTotalSize(m_format);
187         if (m_pWritePointer + totalSize >= m_pEndOfTheBuffer)
188         {
189             return false;
190         }
191
192         alignedEnd = m_pWritePointer + totalSize + sizeof(totalSize);
193
194         memcpy(m_pWritePointer, &totalSize, sizeof(totalSize));
195         m_pWritePointer += sizeof(totalSize);
196
197         unsigned int metadataId = instance.GetMetadataId();
198         _ASSERTE((metadataId & (1 << 31)) == 0);
199         metadataId |= (!isSortedEvent ? 1 << 31 : 0);
200         memcpy(m_pWritePointer, &metadataId, sizeof(metadataId));
201         m_pWritePointer += sizeof(metadataId);
202
203         if (m_format == EventPipeSerializationFormat::NetPerfV3)
204         {
205             DWORD threadId = instance.GetThreadId32();
206             memcpy(m_pWritePointer, &threadId, sizeof(threadId));
207             m_pWritePointer += sizeof(threadId);
208         }
209         else if (m_format == EventPipeSerializationFormat::NetTraceV4)
210         {
211             memcpy(m_pWritePointer, &sequenceNumber, sizeof(sequenceNumber));
212             m_pWritePointer += sizeof(sequenceNumber);
213
214             ULONGLONG threadId = instance.GetThreadId64();
215             memcpy(m_pWritePointer, &threadId, sizeof(threadId));
216             m_pWritePointer += sizeof(threadId);
217
218             memcpy(m_pWritePointer, &captureThreadId, sizeof(captureThreadId));
219             m_pWritePointer += sizeof(captureThreadId);
220
221             memcpy(m_pWritePointer, &captureProcNumber, sizeof(captureProcNumber));
222             m_pWritePointer += sizeof(captureProcNumber);
223
224             memcpy(m_pWritePointer, &stackId, sizeof(stackId));
225             m_pWritePointer += sizeof(stackId);
226         }
227
228         const LARGE_INTEGER* timeStamp = instance.GetTimeStamp();
229         memcpy(m_pWritePointer, timeStamp, sizeof(*timeStamp));
230         m_pWritePointer += sizeof(*timeStamp);
231
232         const GUID* activityId = instance.GetActivityId();
233         memcpy(m_pWritePointer, activityId, sizeof(*activityId));
234         m_pWritePointer += sizeof(*activityId);
235
236         const GUID* relatedActivityId = instance.GetRelatedActivityId();
237         memcpy(m_pWritePointer, relatedActivityId, sizeof(*relatedActivityId));
238         m_pWritePointer += sizeof(*relatedActivityId);
239
240         dataLength = instance.GetDataLength();
241         memcpy(m_pWritePointer, &dataLength, sizeof(dataLength));
242         m_pWritePointer += sizeof(dataLength);
243     }
244     else // using header compression
245     {
246         BYTE flags = 0;
247         BYTE* pWritePointer = m_compressedHeader;
248
249         if (instance.GetMetadataId() != m_lastHeader.MetadataId)
250         {
251             WriteVarUInt32(pWritePointer, instance.GetMetadataId());
252             flags |= 1;
253         }
254         if (isSortedEvent)
255         {
256             flags |= (1 << 6);
257         }
258         
259         if (m_lastHeader.SequenceNumber + (instance.GetMetadataId() != 0 ? 1 : 0) != sequenceNumber ||
260             m_lastHeader.CaptureThreadId != captureThreadId ||
261             m_lastHeader.CaptureProcNumber != captureProcNumber)
262         {
263             WriteVarUInt32(pWritePointer, sequenceNumber - m_lastHeader.SequenceNumber - 1);
264             WriteVarUInt64(pWritePointer, captureThreadId);
265             WriteVarUInt32(pWritePointer, captureProcNumber);
266             flags |= (1 << 1);
267         }
268
269         if (m_lastHeader.ThreadId != instance.GetThreadId64())
270         {
271             WriteVarUInt64(pWritePointer, instance.GetThreadId64());
272             flags |= (1 << 2);
273         }
274
275         if (m_lastHeader.StackId != stackId)
276         {
277             WriteVarUInt32(pWritePointer, stackId);
278             flags |= (1 << 3);
279         }
280
281         const LARGE_INTEGER* timeStamp = instance.GetTimeStamp();
282         WriteVarUInt64(pWritePointer, timeStamp->QuadPart - m_lastHeader.TimeStamp.QuadPart);
283
284         if (memcmp(&m_lastHeader.ActivityId, instance.GetActivityId(), sizeof(GUID)) != 0)
285         {
286             memcpy(pWritePointer, instance.GetActivityId(), sizeof(GUID));
287             pWritePointer += sizeof(GUID);
288             flags |= (1 << 4);
289         }
290
291         if (memcmp(&m_lastHeader.RelatedActivityId, instance.GetRelatedActivityId(), sizeof(GUID)) != 0)
292         {
293             memcpy(pWritePointer, instance.GetRelatedActivityId(), sizeof(GUID));
294             pWritePointer += sizeof(GUID);
295             flags |= (1 << 5);
296         }
297
298         dataLength = instance.GetDataLength();
299         if (m_lastHeader.DataLength != dataLength)
300         {
301             WriteVarUInt32(pWritePointer, dataLength);
302             flags |= (1 << 7);
303         }
304
305         unsigned int bytesWritten = (unsigned int)(pWritePointer - m_compressedHeader);
306         unsigned int totalSize = 1 + bytesWritten + dataLength;
307         if (m_pWritePointer + totalSize >= m_pEndOfTheBuffer)
308         {
309             return false;
310         }
311
312         m_lastHeader.MetadataId = instance.GetMetadataId();
313         m_lastHeader.SequenceNumber = sequenceNumber;
314         m_lastHeader.ThreadId = instance.GetThreadId64();
315         m_lastHeader.CaptureThreadId = captureThreadId;
316         m_lastHeader.CaptureProcNumber = captureProcNumber;
317         m_lastHeader.StackId = stackId;
318         m_lastHeader.TimeStamp.QuadPart = timeStamp->QuadPart;
319         memcpy(&m_lastHeader.ActivityId, instance.GetActivityId(), sizeof(GUID));
320         memcpy(&m_lastHeader.RelatedActivityId, instance.GetRelatedActivityId(), sizeof(GUID));
321         m_lastHeader.DataLength = dataLength;
322
323         alignedEnd = m_pWritePointer + totalSize;
324         *m_pWritePointer = flags;
325         m_pWritePointer++;
326         memcpy(m_pWritePointer, m_compressedHeader, bytesWritten);
327         m_pWritePointer += bytesWritten;
328     }
329
330     if (dataLength > 0)
331     {
332         memcpy(m_pWritePointer, instance.GetData(), dataLength);
333         m_pWritePointer += dataLength;
334     }
335
336     if (m_format == EventPipeSerializationFormat::NetPerfV3)
337     {
338         unsigned int stackSize = instance.GetStackSize();
339         memcpy(m_pWritePointer, &stackSize, sizeof(stackSize));
340         m_pWritePointer += sizeof(stackSize);
341
342         if (stackSize > 0)
343         {
344             memcpy(m_pWritePointer, instance.GetStack(), stackSize);
345             m_pWritePointer += stackSize;
346         }
347     }
348
349     while (m_pWritePointer < alignedEnd)
350     {
351         *m_pWritePointer++ = (BYTE)0; // put padding at the end to get 4 bytes alignment of the payload
352     }
353     _ASSERTE(m_pWritePointer == alignedEnd);
354
355     if (m_minTimeStamp.QuadPart > instance.GetTimeStamp()->QuadPart)
356     {
357         m_minTimeStamp.QuadPart = instance.GetTimeStamp()->QuadPart;
358     }
359     if (m_maxTimeStamp.QuadPart < instance.GetTimeStamp()->QuadPart)
360     {
361         m_maxTimeStamp.QuadPart = instance.GetTimeStamp()->QuadPart;
362     }
363
364     return true;
365 }
366
367 EventPipeEventBlock::EventPipeEventBlock(unsigned int maxBlockSize, EventPipeSerializationFormat format) :
368     EventPipeEventBlockBase(maxBlockSize, format, format >= EventPipeSerializationFormat::NetTraceV4)
369 {}
370
371
372 EventPipeMetadataBlock::EventPipeMetadataBlock(unsigned int maxBlockSize) :
373     EventPipeEventBlockBase(maxBlockSize, EventPipeSerializationFormat::NetTraceV4)
374 {}
375
376 unsigned int GetSequencePointBlockSize(EventPipeSequencePoint* pSequencePoint)
377 {
378     const unsigned int sizeOfSequenceNumber =
379         sizeof(ULONGLONG) +    // thread id
380         sizeof(unsigned int);  // sequence number
381     return sizeof(pSequencePoint->TimeStamp) +
382         sizeof(unsigned int) + // thread count
383         pSequencePoint->ThreadSequenceNumbers.GetCount() * sizeOfSequenceNumber;
384 }
385
386 EventPipeSequencePointBlock::EventPipeSequencePointBlock(EventPipeSequencePoint* pSequencePoint) :
387     EventPipeBlock(GetSequencePointBlockSize(pSequencePoint))
388 {
389     const LARGE_INTEGER timeStamp = pSequencePoint->TimeStamp;
390     memcpy(m_pWritePointer, &timeStamp, sizeof(timeStamp));
391     m_pWritePointer += sizeof(timeStamp);
392
393     const unsigned int threadCount = pSequencePoint->ThreadSequenceNumbers.GetCount();
394     memcpy(m_pWritePointer, &threadCount, sizeof(threadCount));
395     m_pWritePointer += sizeof(threadCount);
396
397     for (ThreadSequenceNumberMap::Iterator pCur = pSequencePoint->ThreadSequenceNumbers.Begin();
398         pCur != pSequencePoint->ThreadSequenceNumbers.End();
399         pCur++)
400     {
401         const ULONGLONG threadId = pCur->Key()->GetThread()->GetOSThreadId();
402         memcpy(m_pWritePointer, &threadId, sizeof(threadId));
403         m_pWritePointer += sizeof(threadId);
404
405         const unsigned int sequenceNumber = pCur->Value();
406         memcpy(m_pWritePointer, &sequenceNumber, sizeof(sequenceNumber));
407         m_pWritePointer += sizeof(sequenceNumber);
408     }
409 }
410
411 EventPipeStackBlock::EventPipeStackBlock(unsigned int maxBlockSize) :
412     EventPipeBlock(maxBlockSize)
413 {
414     Clear();
415 }
416
417 void EventPipeStackBlock::Clear()
418 {
419     m_hasInitialIndex = false;
420     m_initialIndex = 0;
421     m_count = 0;
422     EventPipeBlock::Clear();
423 }
424
425 bool EventPipeStackBlock::WriteStack(DWORD stackId, StackContents* pStack)
426 {
427     CONTRACTL
428     {
429         NOTHROW;
430         GC_NOTRIGGER;
431         MODE_ANY;
432     }
433     CONTRACTL_END;
434
435     if (m_pBlock == NULL)
436     {
437         return false;
438     }
439
440     unsigned int stackSize = pStack->GetSize();
441     unsigned int totalSize = sizeof(stackSize) + stackSize;
442     if (m_pWritePointer + totalSize >= m_pEndOfTheBuffer)
443     {
444         return false;
445     }
446
447     if (!m_hasInitialIndex)
448     {
449         m_hasInitialIndex = true;
450         m_initialIndex = stackId;
451     }
452     m_count++;
453
454     memcpy(m_pWritePointer, &stackSize, sizeof(stackSize));
455     m_pWritePointer += sizeof(stackSize);
456
457     if (stackSize > 0)
458     {
459         memcpy(m_pWritePointer, pStack->GetPointer(), stackSize);
460 #ifdef FEATURE_LARGEADDRESS_SUPPORT
461         for (int i = 0; i < stackSize / sizeof(UINT_PTR); i++)
462         {
463             ((UINT_PTR*)m_pWritePointer)[i] &= INT_MAX;
464         }
465 #endif // FEATURE_LARGEADDRESS_SUPPORT
466         m_pWritePointer += stackSize;
467     }
468
469     return true;
470 }
471
472
473 #endif // FEATURE_PERFTRACING