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 24 ProfilerEventListener() 25 : totalFibersCount(0) 26 { 27 } 28 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 39 virtual void OnThreadsCreated(uint32 threadsCount) override 40 { 41 MT_UNUSED(threadsCount); 42 } 43 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 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 75 virtual void OnThreadCreated(uint32 workerIndex) override 76 { 77 BROFILER_START_THREAD("Scheduler(Worker)"); 78 MT_UNUSED(workerIndex); 79 } 80 81 virtual void OnThreadStarted(uint32 workerIndex) override 82 { 83 MT_UNUSED(workerIndex); 84 } 85 86 virtual void OnThreadStoped(uint32 workerIndex) override 87 { 88 MT_UNUSED(workerIndex); 89 BROFILER_STOP_THREAD(); 90 } 91 92 virtual void OnThreadIdleStarted(uint32 workerIndex) override 93 { 94 MT_UNUSED(workerIndex); 95 } 96 97 virtual void OnThreadIdleFinished(uint32 workerIndex) override 98 { 99 MT_UNUSED(workerIndex); 100 } 101 102 virtual void OnThreadWaitStarted() override 103 { 104 } 105 106 virtual void OnThreadWaitFinished() override 107 { 108 } 109 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 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