1 #include <MTScheduler.h>
2 #include "Profiler.h"
3
4
5 #if defined(MT_INSTRUMENTED_BUILD) && defined(MT_ENABLE_BROFILER_SUPPORT)
6
7 #pragma comment( lib, "BrofilerCore.lib" )
8 #pragma comment( lib, "Advapi32.lib" )
9
10
11 const uint32 MAX_INSTRUMENTED_WORKERS = 8;
12 const char *g_WorkerNames[MAX_INSTRUMENTED_WORKERS] = {"worker0","worker1","worker2","worker3","worker4","worker5","worker6","worker7"};
13
14 class ProfilerEventListener : public MT::IProfilerEventListener
15 {
16 Brofiler::EventStorage* fiberEventStorages[MT::MT_MAX_STANDART_FIBERS_COUNT + MT::MT_MAX_EXTENDED_FIBERS_COUNT];
17 uint32 totalFibersCount;
18
19 static mt_thread_local Brofiler::EventStorage* originalThreadStorage;
20 static mt_thread_local Brofiler::EventStorage* activeThreadStorage;
21
22 public:
23
ProfilerEventListener()24 ProfilerEventListener()
25 : totalFibersCount(0)
26 {
27 }
28
OnFibersCreated(uint32 fibersCount)29 virtual void OnFibersCreated(uint32 fibersCount) override
30 {
31 totalFibersCount = fibersCount;
32 MT_ASSERT(fibersCount <= MT_ARRAY_SIZE(fiberEventStorages), "Too many fibers!");
33 for(uint32 fiberIndex = 0; fiberIndex < fibersCount; fiberIndex++)
34 {
35 Brofiler::RegisterFiber(fiberIndex, &fiberEventStorages[fiberIndex]);
36 }
37 }
38
OnThreadsCreated(uint32 threadsCount)39 virtual void OnThreadsCreated(uint32 threadsCount) override
40 {
41 MT_UNUSED(threadsCount);
42 }
43
OnTemporaryWorkerThreadLeave()44 virtual void OnTemporaryWorkerThreadLeave() override
45 {
46 Brofiler::EventStorage** currentThreadStorageSlot = Brofiler::GetEventStorageSlotForCurrentThread();
47 MT_ASSERT(currentThreadStorageSlot, "Sanity check failed");
48 Brofiler::EventStorage* storage = *currentThreadStorageSlot;
49
50 // if profile session is not active
51 if (storage == nullptr)
52 {
53 return;
54 }
55
56 MT_ASSERT(IsFiberStorage(storage) == false, "Sanity check failed");
57 }
58
OnTemporaryWorkerThreadJoin()59 virtual void OnTemporaryWorkerThreadJoin() override
60 {
61 Brofiler::EventStorage** currentThreadStorageSlot = Brofiler::GetEventStorageSlotForCurrentThread();
62 MT_ASSERT(currentThreadStorageSlot, "Sanity check failed");
63 Brofiler::EventStorage* storage = *currentThreadStorageSlot;
64
65 // if profile session is not active
66 if (storage == nullptr)
67 {
68 return;
69 }
70
71 MT_ASSERT(IsFiberStorage(storage) == false, "Sanity check failed");
72 }
73
74
OnThreadCreated(uint32 workerIndex)75 virtual void OnThreadCreated(uint32 workerIndex) override
76 {
77 BROFILER_START_THREAD("Scheduler(Worker)");
78 MT_UNUSED(workerIndex);
79 }
80
OnThreadStarted(uint32 workerIndex)81 virtual void OnThreadStarted(uint32 workerIndex) override
82 {
83 MT_UNUSED(workerIndex);
84 }
85
OnThreadStoped(uint32 workerIndex)86 virtual void OnThreadStoped(uint32 workerIndex) override
87 {
88 MT_UNUSED(workerIndex);
89 BROFILER_STOP_THREAD();
90 }
91
OnThreadIdleStarted(uint32 workerIndex)92 virtual void OnThreadIdleStarted(uint32 workerIndex) override
93 {
94 MT_UNUSED(workerIndex);
95 }
96
OnThreadIdleFinished(uint32 workerIndex)97 virtual void OnThreadIdleFinished(uint32 workerIndex) override
98 {
99 MT_UNUSED(workerIndex);
100 }
101
OnThreadWaitStarted()102 virtual void OnThreadWaitStarted() override
103 {
104 }
105
OnThreadWaitFinished()106 virtual void OnThreadWaitFinished() override
107 {
108 }
109
OnTaskExecuteStateChanged(MT::Color::Type debugColor,const mt_char * debugID,MT::TaskExecuteState::Type type,int32 fiberIndex)110 virtual void OnTaskExecuteStateChanged(MT::Color::Type debugColor, const mt_char* debugID, MT::TaskExecuteState::Type type, int32 fiberIndex) override
111 {
112 MT_UNUSED(debugColor);
113 MT_UNUSED(debugID);
114 //MT_UNUSED(type);
115
116 MT_ASSERT(fiberIndex < (int32)totalFibersCount, "Sanity check failed");
117
118 Brofiler::EventStorage** currentThreadStorageSlot = Brofiler::GetEventStorageSlotForCurrentThread();
119 MT_ASSERT(currentThreadStorageSlot, "Sanity check failed");
120
121 // if profile session is not active
122 if (*currentThreadStorageSlot == nullptr)
123 {
124 return;
125 }
126
127 // if actual fiber is scheduler internal fiber (don't have event storage for internal scheduler fibers)
128 if (fiberIndex < 0)
129 {
130 return;
131 }
132
133 switch(type)
134 {
135 case MT::TaskExecuteState::START:
136 case MT::TaskExecuteState::RESUME:
137 {
138 MT_ASSERT(originalThreadStorage == nullptr, "Sanity check failed");
139
140 originalThreadStorage = *currentThreadStorageSlot;
141
142 MT_ASSERT(IsFiberStorage(originalThreadStorage) == false, "Sanity check failed");
143
144 Brofiler::EventStorage* currentFiberStorage = nullptr;
145 if (fiberIndex >= (int32)0)
146 {
147 currentFiberStorage = fiberEventStorages[fiberIndex];
148 }
149
150 *currentThreadStorageSlot = currentFiberStorage;
151 activeThreadStorage = currentFiberStorage;
152 Brofiler::FiberSyncData::AttachToThread(currentFiberStorage, MT::ThreadId::Self().AsUInt64());
153 }
154 break;
155
156 case MT::TaskExecuteState::STOP:
157 case MT::TaskExecuteState::SUSPEND:
158 {
159 Brofiler::EventStorage* currentFiberStorage = *currentThreadStorageSlot;
160
161 //////////////////////////////////////////////////////////////////////////
162 Brofiler::EventStorage* checkFiberStorage = nullptr;
163 if (fiberIndex >= (int32)0)
164 {
165 checkFiberStorage = fiberEventStorages[fiberIndex];
166 }
167 MT_ASSERT(checkFiberStorage == currentFiberStorage, "Sanity check failed");
168
169 MT_ASSERT(activeThreadStorage == currentFiberStorage, "Sanity check failed");
170
171 //////////////////////////////////////////////////////////////////////////
172
173 MT_ASSERT(IsFiberStorage(currentFiberStorage) == true, "Sanity check failed");
174
175 Brofiler::FiberSyncData::DetachFromThread(currentFiberStorage);
176
177 *currentThreadStorageSlot = originalThreadStorage;
178 originalThreadStorage = nullptr;
179 }
180 break;
181 }
182 }
183 };
184
185
186 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
187 mt_thread_local Brofiler::EventStorage* ProfilerEventListener::originalThreadStorage = nullptr;
188 mt_thread_local Brofiler::EventStorage* ProfilerEventListener::activeThreadStorage = 0;
189
190 #endif
191
192
GetProfiler()193 MT::IProfilerEventListener* GetProfiler()
194 {
195 #if defined(MT_INSTRUMENTED_BUILD) && defined(MT_ENABLE_BROFILER_SUPPORT)
196 static ProfilerEventListener profilerListener;
197 return &profilerListener;
198 #else
199 return nullptr;
200 #endif
201 }
202
203