mutex.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright 2010-2019 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #include "bx_p.h"
  6. #include <bx/mutex.h>
  7. #if BX_CONFIG_SUPPORTS_THREADING
  8. #if BX_CRT_NONE
  9. # include <bx/cpu.h>
  10. # include "crt0.h"
  11. #elif BX_PLATFORM_ANDROID \
  12. || BX_PLATFORM_LINUX \
  13. || BX_PLATFORM_IOS \
  14. || BX_PLATFORM_OSX \
  15. || BX_PLATFORM_PS4 \
  16. || BX_PLATFORM_RPI
  17. # include <pthread.h>
  18. #elif BX_PLATFORM_WINDOWS \
  19. || BX_PLATFORM_WINRT \
  20. || BX_PLATFORM_XBOXONE
  21. # include <windows.h>
  22. # include <errno.h>
  23. #endif // BX_PLATFORM_
  24. namespace bx
  25. {
  26. #if BX_CRT_NONE
  27. struct State
  28. {
  29. enum Enum
  30. {
  31. Unlocked,
  32. Locked,
  33. Contested,
  34. };
  35. };
  36. Mutex::Mutex()
  37. {
  38. BX_STATIC_ASSERT(sizeof(int32_t) <= sizeof(m_internal) );
  39. uint32_t* futex = (uint32_t*)m_internal;
  40. *futex = State::Unlocked;
  41. }
  42. Mutex::~Mutex()
  43. {
  44. }
  45. void Mutex::lock()
  46. {
  47. uint32_t* futex = (uint32_t*)m_internal;
  48. if (State::Unlocked == bx::atomicCompareAndSwap<uint32_t>(futex, State::Unlocked, State::Locked) )
  49. {
  50. return;
  51. }
  52. while (State::Unlocked != bx::atomicCompareAndSwap<uint32_t>(futex, State::Locked, State::Contested) )
  53. {
  54. crt0::futexWait(futex, State::Contested);
  55. }
  56. }
  57. void Mutex::unlock()
  58. {
  59. uint32_t* futex = (uint32_t*)m_internal;
  60. if (State::Contested == bx::atomicCompareAndSwap<uint32_t>(futex, State::Locked, State::Unlocked) )
  61. {
  62. crt0::futexWake(futex, State::Locked);
  63. }
  64. }
  65. #else
  66. # if BX_PLATFORM_WINDOWS \
  67. || BX_PLATFORM_XBOXONE \
  68. || BX_PLATFORM_WINRT
  69. typedef CRITICAL_SECTION pthread_mutex_t;
  70. typedef unsigned pthread_mutexattr_t;
  71. inline int pthread_mutex_lock(pthread_mutex_t* _mutex)
  72. {
  73. EnterCriticalSection(_mutex);
  74. return 0;
  75. }
  76. inline int pthread_mutex_unlock(pthread_mutex_t* _mutex)
  77. {
  78. LeaveCriticalSection(_mutex);
  79. return 0;
  80. }
  81. inline int pthread_mutex_trylock(pthread_mutex_t* _mutex)
  82. {
  83. return TryEnterCriticalSection(_mutex) ? 0 : EBUSY;
  84. }
  85. inline int pthread_mutex_init(pthread_mutex_t* _mutex, pthread_mutexattr_t* /*_attr*/)
  86. {
  87. # if BX_PLATFORM_WINRT
  88. InitializeCriticalSectionEx(_mutex, 4000, 0); // docs recommend 4000 spincount as sane default
  89. # else
  90. InitializeCriticalSection(_mutex);
  91. # endif // BX_PLATFORM_
  92. return 0;
  93. }
  94. inline int pthread_mutex_destroy(pthread_mutex_t* _mutex)
  95. {
  96. DeleteCriticalSection(_mutex);
  97. return 0;
  98. }
  99. # endif // BX_PLATFORM_
  100. Mutex::Mutex()
  101. {
  102. BX_STATIC_ASSERT(sizeof(pthread_mutex_t) <= sizeof(m_internal) );
  103. pthread_mutexattr_t attr;
  104. # if BX_PLATFORM_WINDOWS \
  105. || BX_PLATFORM_XBOXONE \
  106. || BX_PLATFORM_WINRT
  107. # else
  108. pthread_mutexattr_init(&attr);
  109. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  110. # endif // BX_PLATFORM_
  111. pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
  112. pthread_mutex_init(handle, &attr);
  113. }
  114. Mutex::~Mutex()
  115. {
  116. pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
  117. pthread_mutex_destroy(handle);
  118. }
  119. void Mutex::lock()
  120. {
  121. pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
  122. pthread_mutex_lock(handle);
  123. }
  124. void Mutex::unlock()
  125. {
  126. pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
  127. pthread_mutex_unlock(handle);
  128. }
  129. #endif // BX_CRT_NONE
  130. } // namespace bx
  131. #endif // BX_MUTEX_H_HEADER_GUARD