ThreadPosix.cpp 2.2 KB

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