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 | #ifndef __EVENTPIPE_BUFFER_H__ |
6 | #define __EVENTPIPE_BUFFER_H__ |
7 | |
8 | #ifdef FEATURE_PERFTRACING |
9 | |
10 | #include "eventpipe.h" |
11 | #include "eventpipeevent.h" |
12 | #include "eventpipeeventinstance.h" |
13 | #include "eventpipesession.h" |
14 | |
15 | class EventPipeBuffer |
16 | { |
17 | |
18 | friend class EventPipeBufferList; |
19 | friend class EventPipeBufferManager; |
20 | |
21 | private: |
22 | |
23 | // Instances of EventPipeEventInstance in the buffer must be 8-byte aligned. |
24 | // It is OK for the data payloads to be unaligned because they are opaque blobs that are copied via memcpy. |
25 | const size_t AlignmentSize = 8; |
26 | |
27 | // A pointer to the actual buffer. |
28 | BYTE *m_pBuffer; |
29 | |
30 | // The current write pointer. |
31 | BYTE *m_pCurrent; |
32 | |
33 | // The max write pointer (end of the buffer). |
34 | BYTE *m_pLimit; |
35 | |
36 | // The timestamp of the most recent event in the buffer. |
37 | LARGE_INTEGER m_mostRecentTimeStamp; |
38 | |
39 | // Used by PopNext as input to GetNext. |
40 | // If NULL, no events have been popped. |
41 | // The event will still remain in the buffer after it is popped, but PopNext will not return it again. |
42 | EventPipeEventInstance *m_pLastPoppedEvent; |
43 | |
44 | // Each buffer will become part of a per-thread linked list of buffers. |
45 | // The linked list is invasive, thus we declare the pointers here. |
46 | EventPipeBuffer *m_pPrevBuffer; |
47 | EventPipeBuffer *m_pNextBuffer; |
48 | |
49 | unsigned int GetSize() const |
50 | { |
51 | LIMITED_METHOD_CONTRACT; |
52 | return (unsigned int)(m_pLimit - m_pBuffer); |
53 | } |
54 | |
55 | EventPipeBuffer* GetPrevious() const |
56 | { |
57 | LIMITED_METHOD_CONTRACT; |
58 | return m_pPrevBuffer; |
59 | } |
60 | |
61 | EventPipeBuffer* GetNext() const |
62 | { |
63 | LIMITED_METHOD_CONTRACT; |
64 | return m_pNextBuffer; |
65 | } |
66 | |
67 | void SetPrevious(EventPipeBuffer *pBuffer) |
68 | { |
69 | LIMITED_METHOD_CONTRACT; |
70 | m_pPrevBuffer = pBuffer; |
71 | } |
72 | |
73 | void SetNext(EventPipeBuffer *pBuffer) |
74 | { |
75 | LIMITED_METHOD_CONTRACT; |
76 | m_pNextBuffer = pBuffer; |
77 | } |
78 | |
79 | FORCEINLINE BYTE* GetNextAlignedAddress(BYTE *pAddress) |
80 | { |
81 | LIMITED_METHOD_CONTRACT; |
82 | _ASSERTE(m_pBuffer <= pAddress && m_pLimit > pAddress); |
83 | |
84 | pAddress = (BYTE*)ALIGN_UP(pAddress, AlignmentSize); |
85 | |
86 | _ASSERTE((size_t)pAddress % AlignmentSize == 0); |
87 | return pAddress; |
88 | } |
89 | |
90 | public: |
91 | |
92 | EventPipeBuffer(unsigned int bufferSize); |
93 | ~EventPipeBuffer(); |
94 | |
95 | // Write an event to the buffer. |
96 | // An optional stack trace can be provided for sample profiler events. |
97 | // Otherwise, if a stack trace is needed, one will be automatically collected. |
98 | // Returns: |
99 | // - true: The write succeeded. |
100 | // - false: The write failed. In this case, the buffer should be considered full. |
101 | bool WriteEvent(Thread *pThread, EventPipeSession &session, EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId, LPCGUID pRelatedActivityId, StackContents *pStack = NULL); |
102 | |
103 | // Get the timestamp of the most recent event in the buffer. |
104 | LARGE_INTEGER GetMostRecentTimeStamp() const; |
105 | |
106 | // Clear the buffer. |
107 | void Clear(); |
108 | |
109 | // Get the next event from the buffer as long as it is before the specified timestamp. |
110 | // Input of NULL gets the first event. |
111 | EventPipeEventInstance* GetNext(EventPipeEventInstance *pEvent, LARGE_INTEGER beforeTimeStamp); |
112 | |
113 | // Get the next event from the buffer, but don't mark it read. |
114 | EventPipeEventInstance* PeekNext(LARGE_INTEGER beforeTimeStamp); |
115 | |
116 | // Get the next event from the buffer and mark it as read. |
117 | EventPipeEventInstance* PopNext(LARGE_INTEGER beforeTimeStamp); |
118 | |
119 | #ifdef _DEBUG |
120 | bool EnsureConsistency(); |
121 | #endif // _DEBUG |
122 | }; |
123 | |
124 | #endif // FEATURE_PERFTRACING |
125 | |
126 | #endif // __EVENTPIPE_BUFFER_H__ |
127 | |