da185334a9a25c305bad2448c81b910c84f52f86
[platform/upstream/coreclr.git] / src / vm / eventpipeprovider.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 "eventpipeevent.h"
9 #include "eventpipeprovider.h"
10
11 #ifdef FEATURE_PERFTRACING
12
13 EventPipeProvider::EventPipeProvider(const GUID &providerID)
14 {
15     CONTRACTL
16     {
17         THROWS;
18         GC_NOTRIGGER;
19         MODE_ANY;
20     }
21     CONTRACTL_END;
22
23     m_providerID = providerID;
24     m_enabled = false;
25     m_keywords = 0;
26     m_providerLevel = EventPipeEventLevel::Critical;
27     m_pEventList = new SList<SListElem<EventPipeEvent*>>();
28     m_pCallbackFunction = NULL;
29     m_pCallbackData = NULL;
30
31     // Register the provider.
32     EventPipeConfiguration* pConfig = EventPipe::GetConfiguration();
33     _ASSERTE(pConfig != NULL);
34     pConfig->RegisterProvider(*this);
35 }
36
37 EventPipeProvider::~EventPipeProvider()
38 {
39     CONTRACTL
40     {
41         THROWS;
42         GC_NOTRIGGER;
43         MODE_ANY;
44     }
45     CONTRACTL_END;
46
47     // Unregister the provider.
48     // This call is re-entrant.
49     EventPipeConfiguration* pConfig = EventPipe::GetConfiguration();
50     _ASSERTE(pConfig != NULL);
51     pConfig->UnregisterProvider(*this);
52
53     // Free all of the events.
54     if(m_pEventList != NULL)
55     {
56         // Take the lock before manipulating the list.
57         CrstHolder _crst(EventPipe::GetLock());
58
59         SListElem<EventPipeEvent*> *pElem = m_pEventList->GetHead();
60         while(pElem != NULL)
61         {
62             EventPipeEvent *pEvent = pElem->GetValue();
63             delete pEvent;
64
65             pElem = m_pEventList->GetNext(pElem);
66         }
67
68         delete m_pEventList;
69         m_pEventList = NULL;
70     }
71 }
72
73 const GUID& EventPipeProvider::GetProviderID() const
74 {
75     LIMITED_METHOD_CONTRACT;
76
77     return m_providerID;
78 }
79
80 bool EventPipeProvider::Enabled() const
81 {
82     LIMITED_METHOD_CONTRACT;
83
84     return m_enabled;
85 }
86
87 bool EventPipeProvider::EventEnabled(INT64 keywords) const
88 {
89     LIMITED_METHOD_CONTRACT;
90
91     // The event is enabled if:
92     //  - The provider is enabled.
93     //  - The event keywords are unspecified in the manifest (== 0) or when masked with the enabled config are != 0.
94     return (Enabled() && ((keywords == 0) || ((m_keywords & keywords) != 0)));
95 }
96
97 bool EventPipeProvider::EventEnabled(INT64 keywords, EventPipeEventLevel eventLevel) const
98 {
99     LIMITED_METHOD_CONTRACT;
100
101     // The event is enabled if:
102     //  - The provider is enabled.
103     //  - The event keywords are unspecified in the manifest (== 0) or when masked with the enabled config are != 0.
104     //  - The event level is LogAlways or the provider's verbosity level is set to greater than the event's verbosity level in the manifest.
105     return (EventEnabled(keywords) &&
106         ((eventLevel == EventPipeEventLevel::LogAlways) || (m_providerLevel >= eventLevel)));
107 }
108
109 void EventPipeProvider::SetConfiguration(bool providerEnabled, INT64 keywords, EventPipeEventLevel providerLevel)
110 {
111     CONTRACTL
112     {
113         THROWS;
114         GC_NOTRIGGER;
115         MODE_ANY;
116         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
117     }
118     CONTRACTL_END;
119
120     m_enabled = providerEnabled;
121     m_keywords = keywords;
122     m_providerLevel = providerLevel;
123
124     RefreshAllEvents();
125     InvokeCallback();
126 }
127
128 EventPipeEvent* EventPipeProvider::AddEvent(INT64 keywords, unsigned int eventID, unsigned int eventVersion, EventPipeEventLevel level, bool needStack)
129 {
130     CONTRACTL
131     {
132         THROWS;
133         GC_NOTRIGGER;
134         MODE_ANY;
135     }
136     CONTRACTL_END;
137
138     // Create the event.
139     EventPipeEvent *pEvent = new EventPipeEvent(
140         *this,
141         keywords,
142         eventID,
143         eventVersion,
144         level,
145         needStack);
146
147     // Add it to the list of events.
148     AddEvent(*pEvent);
149     return pEvent;
150 }
151
152 void EventPipeProvider::AddEvent(EventPipeEvent &event)
153 {
154     CONTRACTL
155     {
156         THROWS;
157         GC_NOTRIGGER;
158         MODE_ANY;
159     }
160     CONTRACTL_END;
161
162     // Take the config lock before inserting a new event.
163     CrstHolder _crst(EventPipe::GetLock());
164
165     m_pEventList->InsertTail(new SListElem<EventPipeEvent*>(&event));
166 }
167
168 void EventPipeProvider::RegisterCallback(EventPipeCallback pCallbackFunction, void *pData)
169 {
170     CONTRACTL
171     {
172         THROWS;
173         GC_NOTRIGGER;
174         MODE_ANY;
175     }
176     CONTRACTL_END;
177
178     // Take the config lock before setting the callback.
179     CrstHolder _crst(EventPipe::GetLock());
180
181     if(m_pCallbackFunction == NULL)
182     {
183         m_pCallbackFunction = pCallbackFunction;
184         m_pCallbackData = pData;
185     }
186 }
187
188 void EventPipeProvider::UnregisterCallback(EventPipeCallback pCallbackFunction)
189 {
190     CONTRACTL
191     {
192         THROWS;
193         GC_NOTRIGGER;
194         MODE_ANY;
195     }
196     CONTRACTL_END;
197
198     // Take the config lock before setting the callback.
199     CrstHolder _crst(EventPipe::GetLock());
200
201     if(m_pCallbackFunction == pCallbackFunction)
202     {
203         m_pCallbackFunction = NULL;
204         m_pCallbackData = NULL;
205     }
206 }
207
208 void EventPipeProvider::InvokeCallback()
209 {
210     CONTRACTL
211     {
212         THROWS;
213         GC_NOTRIGGER;
214         MODE_ANY;
215         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
216     }
217     CONTRACTL_END;
218
219     if(m_pCallbackFunction != NULL)
220     {
221         (*m_pCallbackFunction)(
222             &m_providerID,
223             m_enabled,
224             (UCHAR) m_providerLevel,
225             m_keywords,
226             0 /* matchAllKeywords */,
227             NULL /* FilterData */,
228             m_pCallbackData /* CallbackContext */);
229     }
230 }
231
232 void EventPipeProvider::RefreshAllEvents()
233 {
234     CONTRACTL
235     {
236         THROWS;
237         GC_NOTRIGGER;
238         MODE_ANY;
239         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
240     }
241     CONTRACTL_END;
242
243     SListElem<EventPipeEvent*> *pElem = m_pEventList->GetHead();
244     while(pElem != NULL)
245     {
246         EventPipeEvent *pEvent = pElem->GetValue();
247         pEvent->RefreshState();
248
249         pElem = m_pEventList->GetNext(pElem);
250     }
251 }
252
253 #endif // FEATURE_PERFTRACING