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
15class EventPipeBuffer
16{
17
18 friend class EventPipeBufferList;
19 friend class EventPipeBufferManager;
20
21private:
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
90public:
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