Re-Factor EventSource to Support Writing to EventPipe (#11435)
[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, EventPipeCallback pCallbackFunction, void *pCallbackData)
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 = pCallbackFunction;
29     m_pCallbackData = pCallbackData;
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::InvokeCallback()
169 {
170     CONTRACTL
171     {
172         THROWS;
173         GC_NOTRIGGER;
174         MODE_ANY;
175         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
176     }
177     CONTRACTL_END;
178
179     if(m_pCallbackFunction != NULL && !g_fEEShutDown)
180     {
181         (*m_pCallbackFunction)(
182             &m_providerID,
183             m_enabled,
184             (UCHAR) m_providerLevel,
185             m_keywords,
186             0 /* matchAllKeywords */,
187             NULL /* FilterData */,
188             m_pCallbackData /* CallbackContext */);
189     }
190 }
191
192 void EventPipeProvider::RefreshAllEvents()
193 {
194     CONTRACTL
195     {
196         THROWS;
197         GC_NOTRIGGER;
198         MODE_ANY;
199         PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
200     }
201     CONTRACTL_END;
202
203     SListElem<EventPipeEvent*> *pElem = m_pEventList->GetHead();
204     while(pElem != NULL)
205     {
206         EventPipeEvent *pEvent = pElem->GetValue();
207         pEvent->RefreshState();
208
209         pElem = m_pEventList->GetNext(pElem);
210     }
211 }
212
213 #endif // FEATURE_PERFTRACING