[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / eventpipebuffer.h
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 EventPipeThread;
16
17
18 // Synchronization
19 //
20 // EventPipeBuffer starts off writable and accumulates events in a buffer, then at some point converts to be readable and a second thread can
21 // read back the events which have accumulated. The transition occurs when calling ConvertToReadOnly(). Write methods will assert if the buffer
22 // isn't writable and read-related methods will assert if it isn't readable. Methods that have no asserts should have immutable results that
23 // can be used at any point during the buffer's lifetime. The buffer has no internal locks so it is the caller's responsibility to synchronize
24 // their usage.
25 // Writing into the buffer and calling ConvertToReadOnly() is always done with EventPipeThread::m_lock held. The eventual reader thread can do
26 // a few different things to ensure it sees a consistent state:
27 // 1) Take the writer's EventPipeThread::m_lock at least once after the last time the writer writes events
28 // 2) Use a memory barrier that prevents reader loads from being re-ordered earlier, such as the one that will occur implicitly by evaluating
29 //    EventPipeBuffer::GetVolatileState()
30
31
32 enum EventPipeBufferState
33 {
34     // This buffer is currently assigned to a thread and pWriterThread may write events into it
35     // at any time
36     WRITABLE = 0,
37
38     // This buffer has been returned to the EventPipeBufferManager and pWriterThread is guaranteed
39     // to never access it again.
40     READ_ONLY = 1
41 };
42
43 class EventPipeBuffer
44 {
45
46     friend class EventPipeBufferList;
47     friend class EventPipeBufferManager;
48
49 private:
50
51     // Instances of EventPipeEventInstance in the buffer must be 8-byte aligned.
52     // It is OK for the data payloads to be unaligned because they are opaque blobs that are copied via memcpy.
53     const size_t AlignmentSize = 8;
54
55     // State transition WRITABLE -> READ_ONLY only occurs while holding the m_pWriterThread->m_lock;
56     // It can be read at any time
57     Volatile<EventPipeBufferState> m_state;
58
59     // Thread that is/was allowed to write into this buffer when m_state == WRITABLE
60     EventPipeThread* m_pWriterThread;
61
62     // The sequence number corresponding to m_pCurrentReadEvent
63     // Prior to read iteration it is the sequence number of the first event in the buffer
64     unsigned int m_eventSequenceNumber;
65     
66     // A pointer to the actual buffer.
67     BYTE *m_pBuffer;
68
69     // The current write pointer.
70     BYTE *m_pCurrent;
71
72     // The max write pointer (end of the buffer).
73     BYTE *m_pLimit;
74
75     // The timestamp the buffer was created. If our clock source
76     // is monotonic then all events in the buffer should have
77     // timestamp >= this one. If not then all bets are off.
78     LARGE_INTEGER m_creationTimeStamp;
79
80     // Pointer to the current event being read
81     EventPipeEventInstance *m_pCurrentReadEvent;
82
83     // Each buffer will become part of a per-thread linked list of buffers.
84     // The linked list is invasive, thus we declare the pointers here.
85     EventPipeBuffer *m_pPrevBuffer;
86     EventPipeBuffer *m_pNextBuffer;
87
88     unsigned int GetSize() const
89     {
90         LIMITED_METHOD_CONTRACT;
91         return (unsigned int)(m_pLimit - m_pBuffer);
92     }
93
94     EventPipeBuffer* GetPrevious() const
95     {
96         LIMITED_METHOD_CONTRACT;
97         return m_pPrevBuffer;
98     }
99
100     EventPipeBuffer* GetNext() const
101     {
102         LIMITED_METHOD_CONTRACT;
103         return m_pNextBuffer;
104     }
105
106     void SetPrevious(EventPipeBuffer *pBuffer)
107     {
108         LIMITED_METHOD_CONTRACT;
109         m_pPrevBuffer = pBuffer;
110     }
111
112     void SetNext(EventPipeBuffer *pBuffer)
113     {
114         LIMITED_METHOD_CONTRACT;
115         m_pNextBuffer = pBuffer;
116     }
117
118     FORCEINLINE BYTE* GetNextAlignedAddress(BYTE *pAddress)
119     {
120         LIMITED_METHOD_CONTRACT;
121         _ASSERTE(m_pBuffer <= pAddress && pAddress <= m_pLimit);
122
123         pAddress = (BYTE*)ALIGN_UP(pAddress, AlignmentSize);
124
125         _ASSERTE((size_t)pAddress % AlignmentSize == 0);
126         return pAddress;
127     }
128
129 public:
130
131     EventPipeBuffer(unsigned int bufferSize, EventPipeThread* pWriterThread, unsigned int eventSequenceNumber);
132     ~EventPipeBuffer();
133
134     // Write an event to the buffer.
135     // An optional stack trace can be provided for sample profiler events.
136     // Otherwise, if a stack trace is needed, one will be automatically collected.
137     // Returns:
138     //  - true: The write succeeded.
139     //  - false: The write failed.  In this case, the buffer should be considered full.
140     bool WriteEvent(Thread *pThread, EventPipeSession &session, EventPipeEvent &event, EventPipeEventPayload &payload, LPCGUID pActivityId, LPCGUID pRelatedActivityId, StackContents *pStack = NULL);
141
142     // Get the timestamp the buffer was created.
143     LARGE_INTEGER GetCreationTimeStamp() const;
144
145     // Advances read cursor to the next event or NULL if there aren't any more. When the
146     // buffer is first made readable the cursor is automatically positioned on the first
147     // event or NULL if there are no events in the buffer.
148     void MoveNextReadEvent();
149
150     // Returns the event at the current read cursor. The returned event pointer is valid
151     // until the buffer is deleted.
152     EventPipeEventInstance* GetCurrentReadEvent();
153
154     // Gets the sequence number of the event corresponding to GetCurrentReadEvent();
155     unsigned int GetCurrentSequenceNumber();
156
157     // Get the thread that is (or was) assigned to write to this buffer
158     EventPipeThread* GetWriterThread();
159
160     // Check the state of the buffer
161     EventPipeBufferState GetVolatileState();
162
163     // Convert the buffer writable to readable
164     void ConvertToReadOnly();
165
166 #ifdef _DEBUG
167     bool EnsureConsistency();
168 #endif // _DEBUG
169 };
170
171 #endif // FEATURE_PERFTRACING
172
173 #endif // __EVENTPIPE_BUFFER_H__