123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- #include "il2cpp-config.h"
- #if !IL2CPP_THREADS_STD && IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
- #include <limits>
- #include <unistd.h>
- #include <map>
- #include <pthread.h>
- #include <errno.h>
- #include <string.h>
- #if IL2CPP_TARGET_LINUX
- #include <sys/prctl.h>
- #include <sys/resource.h>
- #endif
- #include "ThreadImpl.h"
- #include "PosixHelpers.h"
- namespace il2cpp
- {
- namespace os
- {
- static Event s_ThreadSleepObject;
- #define ASSERT_CALLED_ON_CURRENT_THREAD \
- IL2CPP_ASSERT(pthread_equal (pthread_self (), m_Handle) && "Must be called on current thread!");
- ThreadImpl::ThreadImpl()
- : m_Handle(0)
- , m_StartFunc(NULL)
- , m_StartArg(NULL)
- , m_CurrentWaitObject(NULL)
- , m_StackSize(IL2CPP_DEFAULT_STACK_SIZE)
- , m_ConditionSemaphore(1)
- {
- }
- ThreadImpl::~ThreadImpl()
- {
- }
- ErrorCode ThreadImpl::Run(Thread::StartFunc func, void* arg, int64_t affinityMask)
- {
-
- m_StartFunc = func;
- m_StartArg = arg;
-
- pthread_attr_t attr;
- int s = pthread_attr_init(&attr);
- if (s)
- return kErrorCodeGenFailure;
- #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_AFFINTY)
- #if IL2CPP_THREAD_HAS_CPU_SET
- if (affinityMask != Thread::kThreadAffinityAll)
- {
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
- for (int i = 0; i < 64; ++i)
- {
- if (affinityMask & (1 << i))
- CPU_SET(i, &cpuset);
- }
- pthread_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
- }
- else
- {
-
- pthread_attr_setaffinity_np(&attr, 0, NULL);
- }
- #else
- pthread_attr_setaffinity_np(&attr, 0, NULL);
- #endif
- #endif
- #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_STACKSIZE)
- pthread_attr_setstacksize(&attr, m_StackSize);
- #endif
-
- pthread_t threadId;
- s = pthread_create(&threadId, &attr, &ThreadStartWrapper, this);
- if (s)
- return kErrorCodeGenFailure;
-
- s = pthread_attr_destroy(&attr);
- if (s)
- return kErrorCodeGenFailure;
-
- m_Handle = threadId;
- return kErrorCodeSuccess;
- }
- void* ThreadImpl::ThreadStartWrapper(void* arg)
- {
- ThreadImpl* thread = reinterpret_cast<ThreadImpl*>(arg);
-
-
- thread->m_Handle = pthread_self();
-
-
-
- int returnValue = pthread_detach(thread->m_Handle);
- IL2CPP_ASSERT(returnValue == 0);
- (void)returnValue;
-
- thread->m_StartFunc(thread->m_StartArg);
- return 0;
- }
- uint64_t ThreadImpl::Id()
- {
- return posix::PosixThreadIdToThreadId(m_Handle);
- }
- void ThreadImpl::SetName(const char* name)
- {
-
- if (pthread_self() != m_Handle)
- return;
- #if IL2CPP_TARGET_DARWIN
- pthread_setname_np(name);
- #elif IL2CPP_TARGET_LINUX || IL2CPP_TARGET_ANDROID || IL2CPP_ENABLE_PLATFORM_THREAD_RENAME
- if (pthread_setname_np(m_Handle, name) == ERANGE)
- {
- char buf[16];
- strncpy(buf, name, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- pthread_setname_np(m_Handle, buf);
- }
- #endif
- }
- void ThreadImpl::SetStackSize(size_t newsize)
- {
-
- if (newsize == 0)
- {
- newsize = IL2CPP_DEFAULT_STACK_SIZE;
- }
- m_StackSize = newsize;
- }
- int ThreadImpl::GetMaxStackSize()
- {
- #if IL2CPP_TARGET_DARWIN || IL2CPP_TARGET_LINUX
- struct rlimit lim;
-
- if (getrlimit(RLIMIT_STACK, &lim))
- return INT_MAX;
-
- if (lim.rlim_max > (rlim_t)INT_MAX)
- return INT_MAX;
- return (int)lim.rlim_max;
- #else
- return INT_MAX;
- #endif
- }
- void ThreadImpl::SetPriority(ThreadPriority priority)
- {
-
- }
- ThreadPriority ThreadImpl::GetPriority()
- {
-
- return kThreadPriorityNormal;
- }
- void ThreadImpl::QueueUserAPC(Thread::APCFunc function, void* context)
- {
- IL2CPP_ASSERT(function != NULL);
-
- {
- m_PendingAPCsMutex.Acquire();
- m_PendingAPCs.push_back(APCRequest(function, context));
- m_PendingAPCsMutex.Release();
- }
-
- if (m_CurrentWaitObject.load())
- {
- m_ConditionSemaphore.Release(1);
- }
- }
- void ThreadImpl::CheckForUserAPCAndHandle()
- {
- ASSERT_CALLED_ON_CURRENT_THREAD;
- m_PendingAPCsMutex.Acquire();
- while (!m_PendingAPCs.empty())
- {
- APCRequest apcRequest = m_PendingAPCs.front();
-
-
- m_PendingAPCs.erase(m_PendingAPCs.begin());
-
-
-
- m_PendingAPCsMutex.Release();
-
- apcRequest.callback(apcRequest.context);
-
- m_PendingAPCsMutex.Acquire();
- }
- m_PendingAPCsMutex.Release();
- }
- void ThreadImpl::SetWaitObject(WaitObject* waitObject)
- {
-
- ASSERT_CALLED_ON_CURRENT_THREAD;
-
-
- m_CurrentWaitObject = waitObject;
- }
- void ThreadImpl::Sleep(uint32_t milliseconds, bool interruptible)
- {
- s_ThreadSleepObject.Wait(milliseconds, interruptible);
- }
- uint64_t ThreadImpl::CurrentThreadId()
- {
- return posix::PosixThreadIdToThreadId(pthread_self());
- }
- ThreadImpl* ThreadImpl::GetCurrentThread()
- {
- return Thread::GetCurrentThread()->m_Thread;
- }
- ThreadImpl* ThreadImpl::CreateForCurrentThread()
- {
- ThreadImpl* thread = new ThreadImpl();
- thread->m_Handle = pthread_self();
- return thread;
- }
- bool ThreadImpl::YieldInternal()
- {
- return sched_yield() == 0;
- }
- #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP
- static pthread_key_t s_CleanupKey;
- static Thread::ThreadCleanupFunc s_CleanupFunc;
- static void CleanupThreadIfCanceled(void* arg)
- {
- Thread::ThreadCleanupFunc cleanupFunc = s_CleanupFunc;
- if (cleanupFunc)
- cleanupFunc(arg);
- }
- void ThreadImpl::SetNativeThreadCleanup(Thread::ThreadCleanupFunc cleanupFunction)
- {
- if (cleanupFunction)
- {
- IL2CPP_ASSERT(!s_CleanupFunc);
- s_CleanupFunc = cleanupFunction;
- int result = pthread_key_create(&s_CleanupKey, &CleanupThreadIfCanceled);
- IL2CPP_ASSERT(!result);
- NO_UNUSED_WARNING(result);
- }
- else
- {
- IL2CPP_ASSERT(s_CleanupFunc);
- int result = pthread_key_delete(s_CleanupKey);
- IL2CPP_ASSERT(!result);
- NO_UNUSED_WARNING(result);
- s_CleanupFunc = NULL;
- }
- }
- void ThreadImpl::RegisterCurrentThreadForCleanup(void* arg)
- {
- IL2CPP_ASSERT(s_CleanupFunc);
- pthread_setspecific(s_CleanupKey, arg);
- }
- void ThreadImpl::UnregisterCurrentThreadForCleanup()
- {
- IL2CPP_ASSERT(s_CleanupFunc);
- void* data = pthread_getspecific(s_CleanupKey);
- if (data != NULL)
- pthread_setspecific(s_CleanupKey, NULL);
- }
- #endif
- }
- }
- #endif
|