cfb96fc8d5215131facb5c8dcc51b2b47e1c4180
[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
89     return true;
90 }
91
92 bool EventPipeConfiguration::UnregisterProvider(EventPipeProvider &provider)
93 {
94     CONTRACTL
95     {
96         THROWS;
97         GC_NOTRIGGER;
98         MODE_ANY;
99     }
100     CONTRACTL_END;
101
102     // Take the lock before manipulating the provider list.
103     CrstHolder _crst(EventPipe::GetLock());
104
105     // Find the provider.
106     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
107     while(pElem != NULL)
108     {
109         if(pElem->GetValue() == &provider)
110         {
111             break;
112         }
113
114         pElem = m_pProviderList->GetNext(pElem);
115     }
116
117     // If we found the provider, remove it.
118     if(pElem != NULL)
119     {
120         if(m_pProviderList->FindAndRemove(pElem) != NULL)
121         {
122             return true;
123         }
124     }
125
126     return false;
127 }
128
129 EventPipeProvider* EventPipeConfiguration::GetProvider(const GUID &providerID)
130 {
131     CONTRACTL
132     {
133         THROWS;
134         GC_NOTRIGGER;
135         MODE_ANY;
136     }
137     CONTRACTL_END;
138
139     // Take the lock before touching the provider list to ensure no one tries to
140     // modify the list.
141     CrstHolder _crst(EventPipe::GetLock());
142
143     return GetProviderNoLock(providerID);
144 }
145
146 EventPipeProvider* EventPipeConfiguration::GetProviderNoLock(const GUID &providerID)
147 {
148     CONTRACTL
149     {
150         THROWS;
151         GC_NOTRIGGER;
152         MODE_ANY;
153         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
154     }
155     CONTRACTL_END;
156
157     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
158     while(pElem != NULL)
159     {
160         EventPipeProvider *pProvider = pElem->GetValue();
161         if(pProvider->GetProviderID() == providerID)
162         {
163             return pProvider;
164         }
165
166         pElem = m_pProviderList->GetNext(pElem);
167     }
168
169     return NULL;
170 }
171
172 void EventPipeConfiguration::Enable()
173 {
174     CONTRACTL
175     {
176         THROWS;
177         GC_NOTRIGGER;
178         MODE_ANY;
179         // Lock must be held by EventPipe::Enable.
180         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
181     }
182     CONTRACTL_END;
183
184     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
185     while(pElem != NULL)
186     {
187         // TODO: Only enable the providers that have been explicitly enabled with specified keywords/level.
188         EventPipeProvider *pProvider = pElem->GetValue();
189         pProvider->SetConfiguration(true /* providerEnabled */, 0xFFFFFFFFFFFFFFFF /* keywords */, EventPipeEventLevel::Verbose /* level */);
190
191         pElem = m_pProviderList->GetNext(pElem);
192     }
193
194 }
195
196 void EventPipeConfiguration::Disable()
197 {
198     CONTRACTL
199     {
200         THROWS;
201         GC_NOTRIGGER;
202         MODE_ANY;
203         // Lock must be held by EventPipe::Disable.
204         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
205     }
206     CONTRACTL_END;
207
208     SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
209     while(pElem != NULL)
210     {
211         EventPipeProvider *pProvider = pElem->GetValue();
212         pProvider->SetConfiguration(false /* providerEnabled */, 0 /* keywords */, EventPipeEventLevel::Critical /* level */);
213
214         pElem = m_pProviderList->GetNext(pElem);
215     }
216 }
217
218 EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPipeEvent &sourceEvent, BYTE *pPayloadData, unsigned int payloadLength)
219 {
220     CONTRACTL
221     {
222         THROWS;
223         GC_NOTRIGGER;
224         MODE_ANY;
225     }
226     CONTRACTL_END;
227
228     // The payload of the event should contain:
229     // - GUID ProviderID.
230     // - unsigned int EventID.
231     // - unsigned int EventVersion.
232     // - Optional event description payload.
233
234     // Calculate the size of the event.
235     const GUID &providerID = sourceEvent.GetProvider()->GetProviderID();
236     unsigned int eventID = sourceEvent.GetEventID();
237     unsigned int eventVersion = sourceEvent.GetEventVersion();
238     unsigned int instancePayloadSize = sizeof(providerID) + sizeof(eventID) + sizeof(eventVersion) + payloadLength;
239
240     // Allocate the payload.
241     BYTE *pInstancePayload = new BYTE[instancePayloadSize];
242
243     // Fill the buffer with the payload.
244     BYTE *currentPtr = pInstancePayload;
245
246     // Write the provider ID.
247     memcpy(currentPtr, (BYTE*)&providerID, sizeof(providerID));
248     currentPtr += sizeof(providerID);
249
250     // Write the event ID.
251     memcpy(currentPtr, &eventID, sizeof(eventID));
252     currentPtr += sizeof(eventID);
253
254     // Write the event version.
255     memcpy(currentPtr, &eventVersion, sizeof(eventVersion));
256     currentPtr += sizeof(eventVersion);
257
258     // Write the incoming payload data.
259     memcpy(currentPtr, pPayloadData, payloadLength);
260
261     // Construct the event instance.
262     EventPipeEventInstance *pInstance = new EventPipeEventInstance(
263         *m_pMetadataEvent,
264         GetCurrentThreadId(),
265         pInstancePayload,
266         instancePayloadSize);
267
268     return pInstance;
269 }
270
271 #endif // FEATURE_PERFTRACING