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 2347d53e4dSSergey Makeev #pragma once 2447d53e4dSSergey Makeev 2581ec7369SSergey Makeev #ifndef __MT_THREAD__ 2681ec7369SSergey Makeev #define __MT_THREAD__ 2781ec7369SSergey Makeev 2881ec7369SSergey Makeev 2947d53e4dSSergey Makeev #include <pthread.h> 3047d53e4dSSergey Makeev #include <unistd.h> 3147d53e4dSSergey Makeev #include <time.h> 3247d53e4dSSergey Makeev #include <limits.h> 3347d53e4dSSergey Makeev #include <stdlib.h> 3447d53e4dSSergey Makeev 35f27fe1eeSadmin #ifdef __APPLE_CC__ 36f27fe1eeSadmin #include <thread> 37f27fe1eeSadmin #endif 38f27fe1eeSadmin 39f27fe1eeSadmin #define _DARWIN_C_SOURCE 40f27fe1eeSadmin #include <sys/mman.h> 41f27fe1eeSadmin 42f27fe1eeSadmin #ifndef MAP_ANONYMOUS 43f27fe1eeSadmin #define MAP_ANONYMOUS MAP_ANON 44f27fe1eeSadmin #endif 45f27fe1eeSadmin 46f27fe1eeSadmin #ifndef MAP_STACK 47f27fe1eeSadmin #define MAP_STACK (0) 48f27fe1eeSadmin #endif 49f27fe1eeSadmin 50603f1500SSergey Makeev #include <Platform/Common/MTThread.h> 51*a565da4eSs.makeev_local #include <MTAppInterop.h> 5247d53e4dSSergey Makeev 5347d53e4dSSergey Makeev namespace MT 5447d53e4dSSergey Makeev { 5547d53e4dSSergey Makeev class _Fiber; 5647d53e4dSSergey Makeev 5747d53e4dSSergey Makeev class Thread : public ThreadBase 5847d53e4dSSergey Makeev { 5947d53e4dSSergey Makeev pthread_t thread; 6047d53e4dSSergey Makeev pthread_attr_t threadAttr; 6147d53e4dSSergey Makeev 62a6b7af00SSergey Makeev Memory::StackDesc stackDesc; 63a6b7af00SSergey Makeev 6447d53e4dSSergey Makeev size_t stackSize; 6547d53e4dSSergey Makeev 6647d53e4dSSergey Makeev bool isStarted; 6747d53e4dSSergey Makeev 6847d53e4dSSergey Makeev static void* ThreadFuncInternal(void* pThread) 6947d53e4dSSergey Makeev { 7047d53e4dSSergey Makeev Thread* self = (Thread *)pThread; 7147d53e4dSSergey Makeev self->func(self->funcData); 723b52e8bcSSergey Makeev return nullptr; 7347d53e4dSSergey Makeev } 7447d53e4dSSergey Makeev 7547d53e4dSSergey Makeev public: 7647d53e4dSSergey Makeev 7747d53e4dSSergey Makeev Thread() 78a6b7af00SSergey Makeev : stackSize(0) 7947d53e4dSSergey Makeev , isStarted(false) 8047d53e4dSSergey Makeev { 8147d53e4dSSergey Makeev } 8247d53e4dSSergey Makeev 83f27fe1eeSadmin void* GetStackBottom() 8447d53e4dSSergey Makeev { 85a6b7af00SSergey Makeev return stackDesc.stackBottom; 8647d53e4dSSergey Makeev } 8747d53e4dSSergey Makeev 8847d53e4dSSergey Makeev size_t GetStackSize() 8947d53e4dSSergey Makeev { 9047d53e4dSSergey Makeev return stackSize; 9147d53e4dSSergey Makeev } 9247d53e4dSSergey Makeev 9347d53e4dSSergey Makeev 9447d53e4dSSergey Makeev void Start(size_t _stackSize, TThreadEntryPoint entryPoint, void* userData) 9547d53e4dSSergey Makeev { 9634a394c3SSergey Makeev MT_ASSERT(!isStarted, "Thread already stared"); 9747d53e4dSSergey Makeev 9834a394c3SSergey Makeev MT_ASSERT(func == nullptr, "Thread already started"); 9947d53e4dSSergey Makeev 10047d53e4dSSergey Makeev func = entryPoint; 10147d53e4dSSergey Makeev funcData = userData; 10247d53e4dSSergey Makeev 103a6b7af00SSergey Makeev stackDesc = Memory::AllocStack(_stackSize); 104a6b7af00SSergey Makeev stackSize = stackDesc.GetStackSize(); 10547d53e4dSSergey Makeev 10634a394c3SSergey Makeev MT_ASSERT(stackSize >= PTHREAD_STACK_MIN, "Thread stack to small"); 10747d53e4dSSergey Makeev 10847d53e4dSSergey Makeev int err = pthread_attr_init(&threadAttr); 1091d81bf1fSSergey Makeev MT_USED_IN_ASSERT(err); 11034a394c3SSergey Makeev MT_ASSERT(err == 0, "pthread_attr_init - error"); 11147d53e4dSSergey Makeev 112a6b7af00SSergey Makeev err = pthread_attr_setstack(&threadAttr, stackDesc.stackBottom, stackSize); 1131d81bf1fSSergey Makeev MT_USED_IN_ASSERT(err); 11434a394c3SSergey Makeev MT_ASSERT(err == 0, "pthread_attr_setstack - error"); 11547d53e4dSSergey Makeev 11647d53e4dSSergey Makeev err = pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_JOINABLE); 1171d81bf1fSSergey Makeev MT_USED_IN_ASSERT(err); 11834a394c3SSergey Makeev MT_ASSERT(err == 0, "pthread_attr_setdetachstate - error"); 11947d53e4dSSergey Makeev 12070c02537SSergey Makeev isStarted = true; 12170c02537SSergey Makeev 12247d53e4dSSergey Makeev err = pthread_create(&thread, &threadAttr, ThreadFuncInternal, this); 1231d81bf1fSSergey Makeev MT_USED_IN_ASSERT(err); 12434a394c3SSergey Makeev MT_ASSERT(err == 0, "pthread_create - error"); 12547d53e4dSSergey Makeev } 12647d53e4dSSergey Makeev 12747d53e4dSSergey Makeev void Stop() 12847d53e4dSSergey Makeev { 12934a394c3SSergey Makeev MT_ASSERT(isStarted, "Thread is not started"); 13047d53e4dSSergey Makeev 13147d53e4dSSergey Makeev if (func == nullptr) 13247d53e4dSSergey Makeev { 13347d53e4dSSergey Makeev return; 13447d53e4dSSergey Makeev } 13547d53e4dSSergey Makeev 13647d53e4dSSergey Makeev void *threadStatus = nullptr; 13747d53e4dSSergey Makeev int err = pthread_join(thread, &threadStatus); 1381d81bf1fSSergey Makeev MT_USED_IN_ASSERT(err); 13934a394c3SSergey Makeev MT_ASSERT(err == 0, "pthread_join - error"); 14047d53e4dSSergey Makeev 14147d53e4dSSergey Makeev err = pthread_attr_destroy(&threadAttr); 1421d81bf1fSSergey Makeev MT_USED_IN_ASSERT(err); 14334a394c3SSergey Makeev MT_ASSERT(err == 0, "pthread_attr_destroy - error"); 14447d53e4dSSergey Makeev 14547d53e4dSSergey Makeev func = nullptr; 14647d53e4dSSergey Makeev funcData = nullptr; 14747d53e4dSSergey Makeev 148a6b7af00SSergey Makeev if (stackDesc.stackMemory != nullptr) 14947d53e4dSSergey Makeev { 150a6b7af00SSergey Makeev Memory::FreeStack(stackDesc); 15147d53e4dSSergey Makeev } 15247d53e4dSSergey Makeev 153a6b7af00SSergey Makeev stackSize = 0; 15447d53e4dSSergey Makeev isStarted = false; 15547d53e4dSSergey Makeev } 15647d53e4dSSergey Makeev 15747d53e4dSSergey Makeev bool IsCurrentThread() const 15847d53e4dSSergey Makeev { 15947d53e4dSSergey Makeev if(!isStarted) 16047d53e4dSSergey Makeev { 16147d53e4dSSergey Makeev return false; 16247d53e4dSSergey Makeev } 16347d53e4dSSergey Makeev 16447d53e4dSSergey Makeev pthread_t callThread = pthread_self(); 16547d53e4dSSergey Makeev if (pthread_equal(callThread, thread)) 16647d53e4dSSergey Makeev { 16747d53e4dSSergey Makeev return true; 16847d53e4dSSergey Makeev } 16947d53e4dSSergey Makeev return false; 17047d53e4dSSergey Makeev } 17147d53e4dSSergey Makeev 17247d53e4dSSergey Makeev static int GetNumberOfHardwareThreads() 17347d53e4dSSergey Makeev { 174f27fe1eeSadmin #ifdef __APPLE_CC__ 175f27fe1eeSadmin return std::thread::hardware_concurrency(); 176f27fe1eeSadmin #else 17747d53e4dSSergey Makeev long numberOfProcessors = sysconf( _SC_NPROCESSORS_ONLN ); 17847d53e4dSSergey Makeev return (int)numberOfProcessors; 179f27fe1eeSadmin #endif 18047d53e4dSSergey Makeev } 18147d53e4dSSergey Makeev 18247d53e4dSSergey Makeev static void Sleep(uint32 milliseconds) 18347d53e4dSSergey Makeev { 1842174fd67SSergey Makeev struct timespec req; 18547d53e4dSSergey Makeev time_t sec = (int)(milliseconds/1000); 18647d53e4dSSergey Makeev milliseconds = milliseconds - (sec*1000); 18747d53e4dSSergey Makeev req.tv_sec = sec; 18847d53e4dSSergey Makeev req.tv_nsec = milliseconds * 1000000L; 18947d53e4dSSergey Makeev while (nanosleep(&req,&req) == -1 ) 19047d53e4dSSergey Makeev { 19147d53e4dSSergey Makeev continue; 19247d53e4dSSergey Makeev } 19347d53e4dSSergey Makeev } 19447d53e4dSSergey Makeev 19547d53e4dSSergey Makeev }; 19647d53e4dSSergey Makeev 19747d53e4dSSergey Makeev 19847d53e4dSSergey Makeev } 19947d53e4dSSergey Makeev 20047d53e4dSSergey Makeev 20181ec7369SSergey Makeev #endif 202