ThreadImpl.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #pragma once
  2. #if !IL2CPP_THREADS_STD && IL2CPP_THREADS_PTHREAD
  3. #include <pthread.h>
  4. #include <vector>
  5. #include "PosixWaitObject.h"
  6. #include "os/ErrorCodes.h"
  7. #include "os/Mutex.h"
  8. #include "os/Event.h"
  9. #include "os/Thread.h"
  10. #include "os/WaitStatus.h"
  11. #include "utils/NonCopyable.h"
  12. #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_AFFINTY)
  13. struct cpu_set_t;
  14. int pthread_attr_setaffinity_np(pthread_attr_t *attr, size_t cpusetsize, const cpu_set_t *cpuset);
  15. #endif
  16. #if defined(IL2CPP_ENABLE_PLATFORM_THREAD_RENAME)
  17. int pthread_setname_np(pthread_t handle, const char *name);
  18. #endif
  19. #if !defined(IL2CPP_DEFAULT_STACK_SIZE)
  20. #define IL2CPP_DEFAULT_STACK_SIZE ( 1 * 1024 * 1024) // default .NET stacksize is 1mb
  21. #endif
  22. namespace il2cpp
  23. {
  24. namespace os
  25. {
  26. /// POSIX threads implementation. Supports APCs and interruptible waits.
  27. class ThreadImpl : public il2cpp::utils::NonCopyable
  28. {
  29. public:
  30. ThreadImpl();
  31. ~ThreadImpl();
  32. uint64_t Id();
  33. ErrorCode Run(Thread::StartFunc func, void* arg);
  34. void QueueUserAPC(Thread::APCFunc func, void* context);
  35. void SetName(const std::string& name);
  36. void SetPriority(ThreadPriority priority);
  37. ThreadPriority GetPriority();
  38. void SetStackSize(size_t newsize);
  39. /// Handle any pending APCs.
  40. /// NOTE: Can only be called on current thread.
  41. void CheckForUserAPCAndHandle();
  42. static void Sleep(uint32_t milliseconds, bool interruptible);
  43. static uint64_t CurrentThreadId();
  44. static ThreadImpl* GetCurrentThread();
  45. static ThreadImpl* CreateForCurrentThread();
  46. #if NET_4_0
  47. static bool YieldInternal();
  48. #endif
  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. 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