ThreadPosix.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Util/Thread.h>
  6. #include <AnKi/Util/Logger.h>
  7. #include <AnKi/Util/String.h>
  8. namespace anki
  9. {
  10. void Thread::start(void* userData, ThreadCallback callback, const ThreadCoreAffinityMask& coreAffintyMask)
  11. {
  12. ANKI_ASSERT(!m_started);
  13. ANKI_ASSERT(callback != nullptr);
  14. m_callback = callback;
  15. m_userData = userData;
  16. #if ANKI_EXTRA_CHECKS
  17. m_started = true;
  18. #endif
  19. pthread_attr_t attr;
  20. pthread_attr_init(&attr);
  21. auto pthreadCallback = [](void* ud) -> void* {
  22. ANKI_ASSERT(ud != nullptr);
  23. Thread* thread = static_cast<Thread*>(ud);
  24. // Set thread name
  25. if(thread->m_name[0] != '\0')
  26. {
  27. setNameOfCurrentThread(&thread->m_name[0]);
  28. }
  29. // Call the callback
  30. ThreadCallbackInfo info;
  31. info.m_userData = thread->m_userData;
  32. info.m_threadName = &thread->m_name[0];
  33. const Error err = thread->m_callback(info);
  34. return numberToPtr<void*>(err._getCode());
  35. };
  36. if(ANKI_UNLIKELY(pthread_create(&m_handle, &attr, pthreadCallback, this)))
  37. {
  38. ANKI_UTIL_LOGF("pthread_create() failed");
  39. }
  40. pthread_attr_destroy(&attr);
  41. if(coreAffintyMask.getEnabledBitCount())
  42. {
  43. pinToCores(coreAffintyMask);
  44. }
  45. }
  46. Error Thread::join()
  47. {
  48. void* out;
  49. if(ANKI_UNLIKELY(pthread_join(m_handle, &out)))
  50. {
  51. ANKI_UTIL_LOGF("pthread_join() failed");
  52. }
  53. #if ANKI_EXTRA_CHECKS
  54. m_started = false;
  55. #endif
  56. // Set return error code
  57. return Error(I32(ptrToNumber(out)));
  58. }
  59. void Thread::pinToCores(const ThreadCoreAffinityMask& coreAffintyMask)
  60. {
  61. ANKI_ASSERT(m_started);
  62. cpu_set_t cpus;
  63. CPU_ZERO(&cpus);
  64. ThreadCoreAffinityMask affinity = coreAffintyMask;
  65. while(affinity.getEnabledBitCount() > 0)
  66. {
  67. const U32 msb = affinity.getMostSignificantBit();
  68. ANKI_ASSERT(msb != MAX_U32);
  69. affinity.unset(msb);
  70. CPU_SET(msb, &cpus);
  71. }
  72. #if ANKI_OS_ANDROID
  73. if(sched_setaffinity(pthread_gettid_np(m_handle), sizeof(cpu_set_t), &cpus))
  74. #else
  75. if(pthread_setaffinity_np(m_handle, sizeof(cpu_set_t), &cpus))
  76. #endif
  77. {
  78. ANKI_UTIL_LOGF("pthread_setaffinity_np() failed");
  79. }
  80. }
  81. void Thread::setNameOfCurrentThread(const CString& name)
  82. {
  83. pthread_setname_np(pthread_self(), name.cstr());
  84. }
  85. } // end namespace anki