ThreadImpl.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #pragma once
  2. #if !IL2CPP_THREADS_STD && IL2CPP_THREADS_PTHREAD && !RUNTIME_TINY
  3. #include <pthread.h>
  4. #include <vector>
  5. #include <atomic>
  6. #include "PosixWaitObject.h"
  7. #include "os/ErrorCodes.h"
  8. #include "os/Mutex.h"
  9. #include "os/Event.h"
  10. #include "os/Thread.h"
  11. #include "os/WaitStatus.h"
  12. #include "utils/NonCopyable.h"
  13. #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_AFFINTY)
  14. struct cpu_set_t;
  15. int pthread_attr_setaffinity_np(pthread_attr_t *attr, size_t cpusetsize, const cpu_set_t *cpuset);
  16. #endif
  17. #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_RENAME)
  18. int pthread_setname_np(pthread_t handle, const char *name);
  19. #endif
  20. #if !defined(IL2CPP_DEFAULT_STACK_SIZE)
  21. #define IL2CPP_DEFAULT_STACK_SIZE ( 1 * 1024 * 1024) // default .NET stacksize is 1mb
  22. #endif
  23. namespace il2cpp
  24. {
  25. namespace os
  26. {
  27. /// POSIX threads implementation. Supports APCs and interruptible waits.
  28. class ThreadImpl : public il2cpp::utils::NonCopyable
  29. {
  30. public:
  31. ThreadImpl();
  32. ~ThreadImpl();
  33. uint64_t Id();
  34. ErrorCode Run(Thread::StartFunc func, void* arg, int64_t affinityMask);
  35. void QueueUserAPC(Thread::APCFunc func, void* context);
  36. void SetName(const char* name);
  37. void SetPriority(ThreadPriority priority);
  38. ThreadPriority GetPriority();
  39. void SetStackSize(size_t newsize);
  40. static int GetMaxStackSize();
  41. /// Handle any pending APCs.
  42. /// NOTE: Can only be called on current thread.
  43. void CheckForUserAPCAndHandle();
  44. static void Sleep(uint32_t milliseconds, bool interruptible);
  45. static uint64_t CurrentThreadId();
  46. static ThreadImpl* GetCurrentThread();
  47. static ThreadImpl* CreateForCurrentThread();
  48. static bool YieldInternal();
  49. #if IL2CPP_HAS_NATIVE_THREAD_CLEANUP
  50. static void SetNativeThreadCleanup(Thread::ThreadCleanupFunc cleanupFunction);
  51. static void RegisterCurrentThreadForCleanup(void* arg);
  52. static void UnregisterCurrentThreadForCleanup();
  53. #endif
  54. private:
  55. friend class posix::PosixWaitObject; // SetWaitObject(), CheckForAPCAndHandle()
  56. std::atomic<pthread_t> m_Handle;
  57. /// The synchronization primitive that this thread is currently blocked on.
  58. ///
  59. /// NOTE: This field effectively turns these wait object into shared resources -- which makes deletion
  60. /// a tricky affair. To avoid one thread trying to interrupt a wait while the other thread already
  61. /// is in progress of deleting the wait object, we use a global mutex in PosixWaitObject.cpp that
  62. /// must be locked by any thread trying to trigger an interrupt.
  63. posix::PosixWaitObject* m_CurrentWaitObject;
  64. /// Start data.
  65. Thread::StartFunc m_StartFunc;
  66. void* m_StartArg;
  67. /// List of APC requests for this thread.
  68. struct APCRequest
  69. {
  70. Thread::APCFunc callback;
  71. void* context;
  72. APCRequest(Thread::APCFunc callback, void* context) :
  73. callback(callback), context(context)
  74. {
  75. }
  76. };
  77. pthread_mutex_t m_PendingAPCsMutex;
  78. std::vector<APCRequest> m_PendingAPCs;
  79. size_t m_StackSize; // size of stack (can not be adjusted after thread creation)
  80. /// Set the synchronization object the thread is about to wait on.
  81. /// NOTE: This can only be called on the current thread.
  82. void SetWaitObject(posix::PosixWaitObject* waitObject);
  83. static void* ThreadStartWrapper(void* arg);
  84. };
  85. }
  86. }
  87. #endif