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 
2558964d0bSSergey Makeev namespace MT
2658964d0bSSergey Makeev {
2758964d0bSSergey Makeev 	namespace internal
2858964d0bSSergey Makeev 	{
292b4df162SSergey Makeev 		// Prime numbers for linear congruential generator seed
302b4df162SSergey Makeev 		static const uint32 primeNumbers[] = {
312b4df162SSergey Makeev 			128473, 135349, 159499, 173839, 209213, 241603, 292709, 314723,
322b4df162SSergey Makeev 			343943, 389299, 419473, 465169, 518327, 649921, 748271, 851087,
332b4df162SSergey Makeev 			862171, 974551, 1002973, 1034639, 1096289, 1153123, 1251037, 1299269,
342b4df162SSergey Makeev 			1272941, 1252151, 1231091, 1206761, 1185469, 1169933, 1141351, 1011583 };
352b4df162SSergey Makeev 
GetPrimeNumber(uint32 index)362b4df162SSergey Makeev 		uint32 GetPrimeNumber(uint32 index)
372b4df162SSergey Makeev 		{
3834a394c3SSergey Makeev 			return primeNumbers[index % MT_ARRAY_SIZE(primeNumbers)];
392b4df162SSergey Makeev 		}
402b4df162SSergey Makeev 
412b4df162SSergey Makeev 
422b4df162SSergey Makeev 
ThreadContext()4358964d0bSSergey Makeev 		ThreadContext::ThreadContext()
4458964d0bSSergey Makeev 			: lastActiveFiberContext(nullptr)
4558964d0bSSergey Makeev 			, taskScheduler(nullptr)
4658964d0bSSergey Makeev 			, hasNewTasksEvent(EventReset::AUTOMATIC, true)
4758964d0bSSergey Makeev 			, state(ThreadState::ALIVE)
482b4df162SSergey Makeev 			, workerIndex(0)
493d930776Ss.makeev_local 			, isExternalDescBuffer(false)
5058964d0bSSergey Makeev 		{
513d930776Ss.makeev_local 			 descBuffer = Memory::Alloc( GetMemoryRequrementInBytesForDescBuffer() );
523d930776Ss.makeev_local 		}
533d930776Ss.makeev_local 
ThreadContext(void * externalDescBuffer)543d930776Ss.makeev_local 		ThreadContext::ThreadContext(void* externalDescBuffer)
553d930776Ss.makeev_local 			: lastActiveFiberContext(nullptr)
563d930776Ss.makeev_local 			, taskScheduler(nullptr)
573d930776Ss.makeev_local 			, queue(DummyQueueFlag::IS_DUMMY_QUEUE)
583d930776Ss.makeev_local 			, state(ThreadState::ALIVE)
593d930776Ss.makeev_local 			, workerIndex(0)
603d930776Ss.makeev_local 			, isExternalDescBuffer(true)
613d930776Ss.makeev_local 		{
623d930776Ss.makeev_local 			descBuffer = externalDescBuffer;
6358964d0bSSergey Makeev 		}
6458964d0bSSergey Makeev 
~ThreadContext()6558964d0bSSergey Makeev 		ThreadContext::~ThreadContext()
6658964d0bSSergey Makeev 		{
673d930776Ss.makeev_local 			if (isExternalDescBuffer == false)
683d930776Ss.makeev_local 			{
69d6661c78SSergey Makeev 				Memory::Free(descBuffer);
703d930776Ss.makeev_local 			}
71d6661c78SSergey Makeev 			descBuffer = nullptr;
7258964d0bSSergey Makeev 		}
7358964d0bSSergey Makeev 
GetMemoryRequrementInBytesForDescBuffer()743d930776Ss.makeev_local 		size_t ThreadContext::GetMemoryRequrementInBytesForDescBuffer()
753d930776Ss.makeev_local 		{
763d930776Ss.makeev_local 			return sizeof(internal::GroupedTask) * TASK_BUFFER_CAPACITY;
773d930776Ss.makeev_local 		}
783d930776Ss.makeev_local 
SetThreadIndex(uint32 threadIndex)792b4df162SSergey Makeev 		void ThreadContext::SetThreadIndex(uint32 threadIndex)
802b4df162SSergey Makeev 		{
812b4df162SSergey Makeev 			workerIndex = threadIndex;
822b4df162SSergey Makeev 			random.SetSeed( GetPrimeNumber(threadIndex) );
832b4df162SSergey Makeev 		}
842b4df162SSergey Makeev 
858112dedfSSergey Makeev #ifdef MT_INSTRUMENTED_BUILD
868112dedfSSergey Makeev 
NotifyWaitStarted()873d930776Ss.makeev_local 		void ThreadContext::NotifyWaitStarted()
883d930776Ss.makeev_local 		{
893d930776Ss.makeev_local 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
903d930776Ss.makeev_local 			{
913d930776Ss.makeev_local 				eventListener->OnThreadWaitStarted();
923d930776Ss.makeev_local 			}
933d930776Ss.makeev_local 		}
943d930776Ss.makeev_local 
NotifyWaitFinished()953d930776Ss.makeev_local 		void ThreadContext::NotifyWaitFinished()
963d930776Ss.makeev_local 		{
973d930776Ss.makeev_local 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
983d930776Ss.makeev_local 			{
993d930776Ss.makeev_local 				eventListener->OnThreadWaitFinished();
1003d930776Ss.makeev_local 			}
1013d930776Ss.makeev_local 		}
1023d930776Ss.makeev_local 
NotifyTemporaryWorkerThreadJoin()103*47ecee31Ss.makeev_local 		void ThreadContext::NotifyTemporaryWorkerThreadJoin()
1049c716f68Ss.makeev_local 		{
1059c716f68Ss.makeev_local 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
1069c716f68Ss.makeev_local 			{
107*47ecee31Ss.makeev_local 				eventListener->OnTemporaryWorkerThreadJoin();
1089c716f68Ss.makeev_local 			}
1099c716f68Ss.makeev_local 		}
1109c716f68Ss.makeev_local 
NotifyTemporaryWorkerThreadLeave()111*47ecee31Ss.makeev_local 		void ThreadContext::NotifyTemporaryWorkerThreadLeave()
1129c716f68Ss.makeev_local 		{
1139c716f68Ss.makeev_local 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
1149c716f68Ss.makeev_local 			{
115*47ecee31Ss.makeev_local 				eventListener->OnTemporaryWorkerThreadLeave();
1169c716f68Ss.makeev_local 			}
1179c716f68Ss.makeev_local 		}
1183d930776Ss.makeev_local 
NotifyTaskExecuteStateChanged(MT::Color::Type debugColor,const mt_char * debugID,TaskExecuteState::Type type,int32 fiberIndex)119*47ecee31Ss.makeev_local 		void ThreadContext::NotifyTaskExecuteStateChanged(MT::Color::Type debugColor, const mt_char* debugID, TaskExecuteState::Type type, int32 fiberIndex)
1208112dedfSSergey Makeev 		{
1210727c1f9SSergey Makeev 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
1220727c1f9SSergey Makeev 			{
123*47ecee31Ss.makeev_local 				eventListener->OnTaskExecuteStateChanged(debugColor, debugID, type, fiberIndex);
1240727c1f9SSergey Makeev 			}
1258112dedfSSergey Makeev 		}
1268112dedfSSergey Makeev 
NotifyThreadCreated(uint32 threadIndex)1273d930776Ss.makeev_local 		void ThreadContext::NotifyThreadCreated(uint32 threadIndex)
128a1626843SSergey Makeev 		{
1290727c1f9SSergey Makeev 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
130a1626843SSergey Makeev 			{
1314a90b4a6SSergey Makeev 				eventListener->OnThreadCreated(threadIndex);
132a1626843SSergey Makeev 			}
1330727c1f9SSergey Makeev 		}
1340727c1f9SSergey Makeev 
NotifyThreadStarted(uint32 threadIndex)1353d930776Ss.makeev_local 		void ThreadContext::NotifyThreadStarted(uint32 threadIndex)
1360727c1f9SSergey Makeev 		{
1370727c1f9SSergey Makeev 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
1380727c1f9SSergey Makeev 			{
1394a90b4a6SSergey Makeev 				eventListener->OnThreadStarted(threadIndex);
1400727c1f9SSergey Makeev 			}
1410727c1f9SSergey Makeev 		}
1420727c1f9SSergey Makeev 
NotifyThreadStoped(uint32 threadIndex)1433d930776Ss.makeev_local 		void ThreadContext::NotifyThreadStoped(uint32 threadIndex)
1440727c1f9SSergey Makeev 		{
1450727c1f9SSergey Makeev 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
1460727c1f9SSergey Makeev 			{
1474a90b4a6SSergey Makeev 				eventListener->OnThreadStoped(threadIndex);
1480727c1f9SSergey Makeev 			}
1490727c1f9SSergey Makeev 		}
1500727c1f9SSergey Makeev 
NotifyThreadIdleStarted(uint32 threadIndex)1513d930776Ss.makeev_local 		void ThreadContext::NotifyThreadIdleStarted(uint32 threadIndex)
1520727c1f9SSergey Makeev 		{
1530727c1f9SSergey Makeev 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
1540727c1f9SSergey Makeev 			{
1553d930776Ss.makeev_local 				eventListener->OnThreadIdleStarted(threadIndex);
1564a90b4a6SSergey Makeev 			}
1570727c1f9SSergey Makeev 		}
158a1626843SSergey Makeev 
NotifyThreadIdleFinished(uint32 threadIndex)1593d930776Ss.makeev_local 		void ThreadContext::NotifyThreadIdleFinished(uint32 threadIndex)
1604a90b4a6SSergey Makeev 		{
1614a90b4a6SSergey Makeev 			if (IProfilerEventListener* eventListener = taskScheduler->GetProfilerEventListener())
1624a90b4a6SSergey Makeev 			{
1633d930776Ss.makeev_local 				eventListener->OnThreadIdleFinished(threadIndex);
164a1626843SSergey Makeev 			}
1654a90b4a6SSergey Makeev 		}
1664a90b4a6SSergey Makeev 
1678112dedfSSergey Makeev #endif
1688112dedfSSergey Makeev 
16958964d0bSSergey Makeev 	}
17058964d0bSSergey Makeev 
17158964d0bSSergey Makeev }
172