1f25ce65dSSergey Makeev // The MIT License (MIT) 2f25ce65dSSergey Makeev // 3f25ce65dSSergey Makeev // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev 4f25ce65dSSergey Makeev // 5f25ce65dSSergey Makeev // Permission is hereby granted, free of charge, to any person obtaining a copy 6f25ce65dSSergey Makeev // of this software and associated documentation files (the "Software"), to deal 7f25ce65dSSergey Makeev // in the Software without restriction, including without limitation the rights 8f25ce65dSSergey Makeev // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9f25ce65dSSergey Makeev // copies of the Software, and to permit persons to whom the Software is 10f25ce65dSSergey Makeev // furnished to do so, subject to the following conditions: 11f25ce65dSSergey Makeev // 12f25ce65dSSergey Makeev // The above copyright notice and this permission notice shall be included in 13f25ce65dSSergey Makeev // all copies or substantial portions of the Software. 14f25ce65dSSergey Makeev // 15f25ce65dSSergey Makeev // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f25ce65dSSergey Makeev // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17f25ce65dSSergey Makeev // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18f25ce65dSSergey Makeev // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19f25ce65dSSergey Makeev // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20f25ce65dSSergey Makeev // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21f25ce65dSSergey Makeev // THE SOFTWARE. 22f25ce65dSSergey Makeev 2358964d0bSSergey Makeev #include <MTScheduler.h> 2458964d0bSSergey Makeev 252b4df162SSergey Makeev 2658964d0bSSergey Makeev namespace MT 2758964d0bSSergey Makeev { 2858964d0bSSergey Makeev namespace internal 2958964d0bSSergey Makeev { 302b4df162SSergey Makeev // Prime numbers for linear congruential generator seed 312b4df162SSergey Makeev static const uint32 primeNumbers[] = { 322b4df162SSergey Makeev 128473, 135349, 159499, 173839, 209213, 241603, 292709, 314723, 332b4df162SSergey Makeev 343943, 389299, 419473, 465169, 518327, 649921, 748271, 851087, 342b4df162SSergey Makeev 862171, 974551, 1002973, 1034639, 1096289, 1153123, 1251037, 1299269, 352b4df162SSergey Makeev 1272941, 1252151, 1231091, 1206761, 1185469, 1169933, 1141351, 1011583 }; 362b4df162SSergey Makeev 372b4df162SSergey Makeev uint32 GetPrimeNumber(uint32 index) 382b4df162SSergey Makeev { 3934a394c3SSergey Makeev return primeNumbers[index % MT_ARRAY_SIZE(primeNumbers)]; 402b4df162SSergey Makeev } 412b4df162SSergey Makeev 422b4df162SSergey Makeev 432b4df162SSergey Makeev 4458964d0bSSergey Makeev ThreadContext::ThreadContext() 4558964d0bSSergey Makeev : lastActiveFiberContext(nullptr) 4658964d0bSSergey Makeev , taskScheduler(nullptr) 4758964d0bSSergey Makeev , hasNewTasksEvent(EventReset::AUTOMATIC, true) 4858964d0bSSergey Makeev , state(ThreadState::ALIVE) 492b4df162SSergey Makeev , workerIndex(0) 5058964d0bSSergey Makeev { 51d6661c78SSergey Makeev descBuffer = Memory::Alloc( sizeof(internal::GroupedTask) * TASK_BUFFER_CAPACITY ); 5258964d0bSSergey Makeev } 5358964d0bSSergey Makeev 5458964d0bSSergey Makeev ThreadContext::~ThreadContext() 5558964d0bSSergey Makeev { 56d6661c78SSergey Makeev Memory::Free(descBuffer); 57d6661c78SSergey Makeev descBuffer = nullptr; 5858964d0bSSergey Makeev } 5958964d0bSSergey Makeev 602b4df162SSergey Makeev void ThreadContext::SetThreadIndex(uint32 threadIndex) 612b4df162SSergey Makeev { 622b4df162SSergey Makeev workerIndex = threadIndex; 632b4df162SSergey Makeev random.SetSeed( GetPrimeNumber(threadIndex) ); 642b4df162SSergey Makeev } 652b4df162SSergey Makeev 66806ef292SSergey Makeev void ThreadContext::RestoreAwaitingTasks(TaskGroup taskGroup) 6758964d0bSSergey Makeev { 6834a394c3SSergey Makeev MT_ASSERT(taskScheduler, "Invalid Task Scheduler"); 6934a394c3SSergey Makeev MT_ASSERT(taskScheduler->IsWorkerThread(), "Can't use RunAsync outside Task. Use TaskScheduler.RunAsync() instead."); 7058964d0bSSergey Makeev 71806ef292SSergey Makeev TaskScheduler::TaskGroupDescription & groupDesc = taskScheduler->GetGroupDesc(taskGroup); 72806ef292SSergey Makeev ConcurrentQueueLIFO<FiberContext*> & groupQueue = groupDesc.GetWaitQueue(); 7358964d0bSSergey Makeev 7458964d0bSSergey Makeev if (groupQueue.IsEmpty()) 7558964d0bSSergey Makeev { 7658964d0bSSergey Makeev return; 7758964d0bSSergey Makeev } 7858964d0bSSergey Makeev 7958964d0bSSergey Makeev //copy awaiting tasks list to stack 80a101e543SSergey Makeev StackArray<FiberContext*, MT_MAX_FIBERS_COUNT> groupQueueCopy(MT_MAX_FIBERS_COUNT, nullptr); 81a101e543SSergey Makeev size_t taskCount = groupQueue.PopAll(groupQueueCopy.Begin(), groupQueueCopy.Size()); 8258964d0bSSergey Makeev 83d6661c78SSergey Makeev ArrayView<internal::GroupedTask> buffer(descBuffer, taskCount); 8458964d0bSSergey Makeev 8558964d0bSSergey Makeev TaskScheduler & scheduler = *(taskScheduler); 861e8563ffSSergey Makeev size_t bucketCount = MT::Min((size_t)scheduler.GetWorkerCount(), taskCount); 8756aa031bSSergey Makeev ArrayView<internal::TaskBucket> buckets(MT_ALLOCATE_ON_STACK(sizeof(internal::TaskBucket) * bucketCount), bucketCount); 8858964d0bSSergey Makeev 89754cb997SSergey Makeev internal::DistibuteDescriptions( TaskGroup(TaskGroup::ASSIGN_FROM_CONTEXT), groupQueueCopy.Begin(), buffer, buckets); 9058964d0bSSergey Makeev scheduler.RunTasksImpl(buckets, nullptr, true); 9158964d0bSSergey Makeev } 9258964d0bSSergey Makeev 938112dedfSSergey Makeev #ifdef MT_INSTRUMENTED_BUILD 948112dedfSSergey Makeev 958112dedfSSergey Makeev void ThreadContext::NotifyTaskFinished(const internal::TaskDesc & desc) 968112dedfSSergey Makeev { 978112dedfSSergey Makeev ProfileEventDesc eventDesc; 98a1626843SSergey Makeev eventDesc.id = desc.debugID; 99a1626843SSergey Makeev eventDesc.colorIndex = desc.colorIndex; 1008112dedfSSergey Makeev eventDesc.type = ProfileEventType::TASK_DONE; 101*0727c1f9SSergey Makeev eventDesc.timeStampMicroSeconds = taskScheduler->GetTimeStamp(); 102*0727c1f9SSergey Makeev 103*0727c1f9SSergey Makeev if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener()) 104*0727c1f9SSergey Makeev { 105*0727c1f9SSergey Makeev eventListener->OnTaskFinished(eventDesc.timeStampMicroSeconds, desc.debugID); 106*0727c1f9SSergey Makeev } 107aac5f829SSergey Makeev 1088112dedfSSergey Makeev profileEvents.Push(std::move(eventDesc)); 1098112dedfSSergey Makeev } 1108112dedfSSergey Makeev 1118112dedfSSergey Makeev void ThreadContext::NotifyTaskResumed(const internal::TaskDesc & desc) 1128112dedfSSergey Makeev { 1138112dedfSSergey Makeev ProfileEventDesc eventDesc; 114a1626843SSergey Makeev eventDesc.id = desc.debugID; 115a1626843SSergey Makeev eventDesc.colorIndex = desc.colorIndex; 1168112dedfSSergey Makeev eventDesc.type = ProfileEventType::TASK_RESUME; 117*0727c1f9SSergey Makeev eventDesc.timeStampMicroSeconds = taskScheduler->GetTimeStamp(); 118*0727c1f9SSergey Makeev 119*0727c1f9SSergey Makeev if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener()) 120*0727c1f9SSergey Makeev { 121*0727c1f9SSergey Makeev eventListener->OnTaskResumed(eventDesc.timeStampMicroSeconds, desc.debugID); 122*0727c1f9SSergey Makeev } 123*0727c1f9SSergey Makeev 1248112dedfSSergey Makeev profileEvents.Push(std::move(eventDesc)); 1258112dedfSSergey Makeev } 1268112dedfSSergey Makeev 1278112dedfSSergey Makeev void ThreadContext::NotifyTaskYielded(const internal::TaskDesc & desc) 1288112dedfSSergey Makeev { 1298112dedfSSergey Makeev ProfileEventDesc eventDesc; 130a1626843SSergey Makeev eventDesc.id = desc.debugID; 131a1626843SSergey Makeev eventDesc.colorIndex = desc.colorIndex; 1328112dedfSSergey Makeev eventDesc.type = ProfileEventType::TASK_YIELD; 133*0727c1f9SSergey Makeev eventDesc.timeStampMicroSeconds = taskScheduler->GetTimeStamp(); 134*0727c1f9SSergey Makeev 135*0727c1f9SSergey Makeev if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener()) 136*0727c1f9SSergey Makeev { 137*0727c1f9SSergey Makeev eventListener->OnTaskYielded(eventDesc.timeStampMicroSeconds, desc.debugID); 138*0727c1f9SSergey Makeev } 139*0727c1f9SSergey Makeev 1408112dedfSSergey Makeev profileEvents.Push(std::move(eventDesc)); 1418112dedfSSergey Makeev } 1428112dedfSSergey Makeev 143*0727c1f9SSergey Makeev void ThreadContext::NotifyThreadCreate(uint32 threadIndex) 144a1626843SSergey Makeev { 145*0727c1f9SSergey Makeev if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener()) 146a1626843SSergey Makeev { 147*0727c1f9SSergey Makeev eventListener->OnThreadCreated(taskScheduler->GetTimeStamp(), threadIndex); 148a1626843SSergey Makeev } 149*0727c1f9SSergey Makeev } 150*0727c1f9SSergey Makeev 151*0727c1f9SSergey Makeev void ThreadContext::NotifyThreadStart(uint32 threadIndex) 152*0727c1f9SSergey Makeev { 153*0727c1f9SSergey Makeev if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener()) 154*0727c1f9SSergey Makeev { 155*0727c1f9SSergey Makeev eventListener->OnThreadStarted(taskScheduler->GetTimeStamp(), threadIndex); 156*0727c1f9SSergey Makeev } 157*0727c1f9SSergey Makeev } 158*0727c1f9SSergey Makeev 159*0727c1f9SSergey Makeev void ThreadContext::NotifyThreadStop(uint32 threadIndex) 160*0727c1f9SSergey Makeev { 161*0727c1f9SSergey Makeev if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener()) 162*0727c1f9SSergey Makeev { 163*0727c1f9SSergey Makeev eventListener->OnThreadStoped(taskScheduler->GetTimeStamp(), threadIndex); 164*0727c1f9SSergey Makeev } 165*0727c1f9SSergey Makeev } 166*0727c1f9SSergey Makeev 167*0727c1f9SSergey Makeev void ThreadContext::NotifyThreadAwait(uint64 timeStampMicroSecondsFrom, uint64 timeStampMicroSecondsTo, uint32 threadIndex) 168*0727c1f9SSergey Makeev { 169*0727c1f9SSergey Makeev if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener()) 170*0727c1f9SSergey Makeev { 171*0727c1f9SSergey Makeev eventListener->OnThreadIdle(timeStampMicroSecondsFrom, timeStampMicroSecondsTo, threadIndex); 172*0727c1f9SSergey Makeev } 173a1626843SSergey Makeev 174a1626843SSergey Makeev } 175a1626843SSergey Makeev 176a1626843SSergey Makeev 1778112dedfSSergey Makeev 1788112dedfSSergey Makeev #endif 1798112dedfSSergey Makeev 18058964d0bSSergey Makeev } 18158964d0bSSergey Makeev 18258964d0bSSergey Makeev } 183