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