Re-Factor EventSource to Support Writing to EventPipe (#11435)
[platform/upstream/coreclr.git] / src / vm / eventpipeconfiguration.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 "eventpipe.h"
7 #include "eventpipeconfiguration.h"
8 #include "eventpipeeventinstance.h"
9 #include "eventpipeprovider.h"
10
11 #ifdef FEATURE_PERFTRACING
12
13 // {5291C09C-2660-4D6A-83A3-C383FD020DEC}
14 const GUID EventPipeConfiguration::s_configurationProviderID =
15     { 0x5291c09c, 0x2660, 0x4d6a, { 0x83, 0xa3, 0xc3, 0x83, 0xfd, 0x2, 0xd, 0xec } };
16
17 EventPipeConfiguration::EventPipeConfiguration()
18 {
19     STANDARD_VM_CONTRACT;
20
21     m_pProviderList = new SList<SListElem<EventPipeProvider*>>();
22 }
23
24 EventPipeConfiguration::~EventPipeConfiguration()
25 {
26     CONTRACTL
27     {
28         THROWS;
29         GC_TRIGGERS;
30         MODE_ANY;
31     }
32     CONTRACTL_END;
33
34     if(m_pProviderList != NULL)
35     {
36         delete(m_pProviderList);
37         m_pProviderList = NULL;
38     }
39 }
40
41 void EventPipeConfiguration::Initialize()
42 {
43     CONTRACTL
44     {
45         THROWS;
46         GC_NOTRIGGER;
47         MODE_ANY;
48     }
49     CONTRACTL_END;
50
51     // Create the configuration provider.
52     m_pConfigProvider = new EventPipeProvider(s_configurationProviderID);
53
54     // Create the metadata event.
55     m_pMetadataEvent = m_pConfigProvider->AddEvent(
56         0,      /* keywords */
57         0,      /* eventID */
58         0,      /* eventVersion */
59         EventPipeEventLevel::Critical,
60         false); /* needStack */
61 }
62
63 bool EventPipeConfiguration::RegisterProvider(EventPipeProvider &provider)
64 {
65     CONTRACTL
66     {
67         THROWS;
68         GC_NOTRIGGER;
69         MODE_ANY;
70     }
71     CONTRACTL_END;
72
73     // Take the lock before manipulating the provider list.
74     CrstHolder _crst(EventPipe::GetLock());
75
76     // See if we've already registered this provider.
77     EventPipeProvider *pExistingProvider = GetProviderNoLock(provider.GetProviderID());
78     if(pExistingProvider != NULL)
79     {
80         return false;
81     }
82
83     // The provider has not been registered, so register it.
84     m_pProviderList->InsertTail(new SListElem<EventPipeProvider*>(&provider));
85
86     // TODO: Set the provider configuration and enable it if we know
87     // anything about the provider before it is registered.
88     provider.SetConfiguration(true /* providerEnabled */, 0xFFFFFFFFFFFFFFFF /* keywords */, EventPipeEventLevel::Verbose /* level */);
89
90     return true;
91 }
92
93 bool EventPipeConfiguration::UnregisterProvider(EventPipeProvider &provider)
94 {
95     CONTRACTL
96     {
97         THROWS;
98         GC_NOTRIGGER;
99         MODE_ANY;
100     }
101     CONTRACTL_END;
102
103     // Take the lock before manipulating the provider list.
104     CrstHolder _crst(EventPipe::GetLock());
105
106     // Find the provider.
107     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
108     while(pElem != NULL)
109     {
110         if(pElem->GetValue() == &provider)
111         {
112             break;
113         }
114
115         pElem = m_pProviderList->GetNext(pElem);
116     }
117
118     // If we found the provider, remove it.
119     if(pElem != NULL)
120     {
121         if(m_pProviderList->FindAndRemove(pElem) != NULL)
122         {
123             return true;
124         }
125     }
126
127     return false;
128 }
129
130 EventPipeProvider* EventPipeConfiguration::GetProvider(const GUID &providerID)
131 {
132     CONTRACTL
133     {
134         THROWS;
135         GC_NOTRIGGER;
136         MODE_ANY;
137     }
138     CONTRACTL_END;
139
140     // Take the lock before touching the provider list to ensure no one tries to
141     // modify the list.
142     CrstHolder _crst(EventPipe::GetLock());
143
144     return GetProviderNoLock(providerID);
145 }
146
147 EventPipeProvider* EventPipeConfiguration::GetProviderNoLock(const GUID &providerID)
148 {
149     CONTRACTL
150     {
151         THROWS;
152         GC_NOTRIGGER;
153         MODE_ANY;
154         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
155     }
156     CONTRACTL_END;
157
158     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
159     while(pElem != NULL)
160     {
161         EventPipeProvider *pProvider = pElem->GetValue();
162         if(pProvider->GetProviderID() == providerID)
163         {
164             return pProvider;
165         }
166
167         pElem = m_pProviderList->GetNext(pElem);
168     }
169
170     return NULL;
171 }
172
173 void EventPipeConfiguration::Enable()
174 {
175     CONTRACTL
176     {
177         THROWS;
178         GC_NOTRIGGER;
179         MODE_ANY;
180         // Lock must be held by EventPipe::Enable.
181         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
182     }
183     CONTRACTL_END;
184
185     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
186     while(pElem != NULL)
187     {
188         // TODO: Only enable the providers that have been explicitly enabled with specified keywords/level.
189         EventPipeProvider *pProvider = pElem->GetValue();
190         pProvider->SetConfiguration(true /* providerEnabled */, 0xFFFFFFFFFFFFFFFF /* keywords */, EventPipeEventLevel::Verbose /* level */);
191
192         pElem = m_pProviderList->GetNext(pElem);
193     }
194
195 }
196
197 void EventPipeConfiguration::Disable()
198 {
199     CONTRACTL
200     {
201         THROWS;
202         GC_NOTRIGGER;
203         MODE_ANY;
204         // Lock must be held by EventPipe::Disable.
205         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
206     }
207     CONTRACTL_END;
208
209     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
210     while(pElem != NULL)
211     {
212         EventPipeProvider *pProvider = pElem->GetValue();
213         pProvider->SetConfiguration(false /* providerEnabled */, 0 /* keywords */, EventPipeEventLevel::Critical /* level */);
214
215         pElem = m_pProviderList->GetNext(pElem);
216     }
217 }
218
219 EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEvent &sourceEvent, BYTE *pPayloadData, unsigned int payloadLength)
220 {
221     CONTRACTL
222     {
223         THROWS;
224         GC_NOTRIGGER;
225         MODE_ANY;
226     }
227     CONTRACTL_END;
228
229     // The payload of the event should contain:
230     // - GUID ProviderID.
231     // - unsigned int EventID.
232     // - unsigned int EventVersion.
233     // - Optional event description payload.
234
235     // Calculate the size of the event.
236     const GUID &providerID = sourceEvent.GetProvider()->GetProviderID();
237     unsigned int eventID = sourceEvent.GetEventID();
238     unsigned int eventVersion = sourceEvent.GetEventVersion();
239     unsigned int instancePayloadSize = sizeof(providerID) + sizeof(eventID) + sizeof(eventVersion) + payloadLength;
240
241     // Allocate the payload.
242     BYTE *pInstancePayload = new BYTE[instancePayloadSize];
243
244     // Fill the buffer with the payload.
245     BYTE *currentPtr = pInstancePayload;
246
247     // Write the provider ID.
248     memcpy(currentPtr, (BYTE*)&providerID, sizeof(providerID));
249     currentPtr += sizeof(providerID);
250
251     // Write the event ID.
252     memcpy(currentPtr, &eventID, sizeof(eventID));
253     currentPtr += sizeof(eventID);
254
255     // Write the event version.
256     memcpy(currentPtr, &eventVersion, sizeof(eventVersion));
257     currentPtr += sizeof(eventVersion);
258
259     // Write the incoming payload data.
260     memcpy(currentPtr, pPayloadData, payloadLength);
261
262     // Construct the event instance.
263     EventPipeEventInstance *pInstance = new EventPipeEventInstance(
264         *m_pMetadataEvent,
265         GetCurrentThreadId(),
266         pInstancePayload,
267         instancePayloadSize);
268
269     return pInstance;
270 }
271
272 #endif // FEATURE_PERFTRACING