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 262b4df162SSergey Makeev 272b4df162SSergey Makeev 282b4df162SSergey Makeev 292b4df162SSergey Makeev 302b4df162SSergey Makeev 3158964d0bSSergey Makeev namespace MT 3258964d0bSSergey Makeev { 3358964d0bSSergey Makeev namespace internal 3458964d0bSSergey Makeev { 3558964d0bSSergey Makeev static const size_t TASK_BUFFER_CAPACITY = 4096; 3658964d0bSSergey Makeev 372b4df162SSergey Makeev // Prime numbers for linear congruential generator seed 382b4df162SSergey Makeev static const uint32 primeNumbers[] = { 392b4df162SSergey Makeev 128473, 135349, 159499, 173839, 209213, 241603, 292709, 314723, 402b4df162SSergey Makeev 343943, 389299, 419473, 465169, 518327, 649921, 748271, 851087, 412b4df162SSergey Makeev 862171, 974551, 1002973, 1034639, 1096289, 1153123, 1251037, 1299269, 422b4df162SSergey Makeev 1272941, 1252151, 1231091, 1206761, 1185469, 1169933, 1141351, 1011583 }; 432b4df162SSergey Makeev 442b4df162SSergey Makeev uint32 GetPrimeNumber(uint32 index) 452b4df162SSergey Makeev { 462b4df162SSergey Makeev return primeNumbers[index % ARRAY_SIZE(primeNumbers)]; 472b4df162SSergey Makeev } 482b4df162SSergey Makeev 492b4df162SSergey Makeev 502b4df162SSergey Makeev 5158964d0bSSergey Makeev ThreadContext::ThreadContext() 5258964d0bSSergey Makeev : lastActiveFiberContext(nullptr) 5358964d0bSSergey Makeev , taskScheduler(nullptr) 5458964d0bSSergey Makeev , hasNewTasksEvent(EventReset::AUTOMATIC, true) 5558964d0bSSergey Makeev , state(ThreadState::ALIVE) 5658964d0bSSergey Makeev , descBuffer(TASK_BUFFER_CAPACITY) 572b4df162SSergey Makeev , workerIndex(0) 5858964d0bSSergey Makeev { 5958964d0bSSergey Makeev } 6058964d0bSSergey Makeev 6158964d0bSSergey Makeev ThreadContext::~ThreadContext() 6258964d0bSSergey Makeev { 6358964d0bSSergey Makeev } 6458964d0bSSergey Makeev 652b4df162SSergey Makeev void ThreadContext::SetThreadIndex(uint32 threadIndex) 662b4df162SSergey Makeev { 672b4df162SSergey Makeev workerIndex = threadIndex; 682b4df162SSergey Makeev random.SetSeed( GetPrimeNumber(threadIndex) ); 692b4df162SSergey Makeev } 702b4df162SSergey Makeev 7158964d0bSSergey Makeev void ThreadContext::RestoreAwaitingTasks(TaskGroup::Type taskGroup) 7258964d0bSSergey Makeev { 7358964d0bSSergey Makeev ASSERT(taskScheduler, "Invalid Task Scheduler"); 7458964d0bSSergey Makeev ASSERT(taskScheduler->IsWorkerThread(), "Can't use RunAsync outside Task. Use TaskScheduler.RunAsync() instead."); 7558964d0bSSergey Makeev 7658964d0bSSergey Makeev ConcurrentQueueLIFO<FiberContext*> & groupQueue = taskScheduler->waitTaskQueues[taskGroup]; 7758964d0bSSergey Makeev 7858964d0bSSergey Makeev if (groupQueue.IsEmpty()) 7958964d0bSSergey Makeev { 8058964d0bSSergey Makeev return; 8158964d0bSSergey Makeev } 8258964d0bSSergey Makeev 8358964d0bSSergey Makeev //copy awaiting tasks list to stack 84*a101e543SSergey Makeev StackArray<FiberContext*, MT_MAX_FIBERS_COUNT> groupQueueCopy(MT_MAX_FIBERS_COUNT, nullptr); 85*a101e543SSergey Makeev size_t taskCount = groupQueue.PopAll(groupQueueCopy.Begin(), groupQueueCopy.Size()); 8658964d0bSSergey Makeev 87*a101e543SSergey Makeev WrapperArray<internal::GroupedTask> buffer(&descBuffer.front(), taskCount); 8858964d0bSSergey Makeev 8958964d0bSSergey Makeev TaskScheduler & scheduler = *(taskScheduler); 9058964d0bSSergey Makeev size_t bucketCount = Min((size_t)scheduler.GetWorkerCount(), taskCount); 91*a101e543SSergey Makeev WrapperArray<internal::TaskBucket> buckets(ALLOCATE_ON_STACK(sizeof(internal::TaskBucket) * bucketCount), bucketCount); 9258964d0bSSergey Makeev 93*a101e543SSergey Makeev internal::DistibuteDescriptions(TaskGroup::GROUP_UNDEFINED, groupQueueCopy.Begin(), buffer, buckets); 9458964d0bSSergey Makeev scheduler.RunTasksImpl(buckets, nullptr, true); 9558964d0bSSergey Makeev } 9658964d0bSSergey Makeev 9758964d0bSSergey Makeev } 9858964d0bSSergey Makeev 9958964d0bSSergey Makeev } 100