lightrwlock.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #include "lightrwlock.h"
  2. #include <util/system/spinlock.h>
  3. #if defined(_linux_) && !defined(_tsan_enabled_)
  4. using namespace NS_LightRWLock;
  5. void TLightRWLock::WaitForUntrappedShared() {
  6. for (;;) {
  7. for (ui32 i = 0; i < SpinCount_; ++i) {
  8. SpinLockPause();
  9. if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
  10. return;
  11. }
  12. SequenceStore(UnshareFutex_, 1);
  13. if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
  14. AtomicStore(UnshareFutex_, 0);
  15. return;
  16. }
  17. FutexWait(UnshareFutex_, 1);
  18. }
  19. }
  20. void TLightRWLock::WaitForExclusiveAndUntrappedShared() {
  21. for (;;) {
  22. for (ui32 i = 0; i < SpinCount_; ++i) {
  23. SpinLockPause();
  24. if (AtomicLoad(Counter_) >= 0)
  25. goto try_to_get_lock;
  26. if (AtomicLoad(TrappedFutex_) == 1)
  27. goto skip_store_trapped;
  28. }
  29. SequenceStore(TrappedFutex_, 1);
  30. skip_store_trapped:
  31. if (AtomicLoad(Counter_) < 0) {
  32. FutexWait(TrappedFutex_, 1);
  33. }
  34. try_to_get_lock:
  35. if (!AtomicSetBit(Counter_, 31))
  36. break;
  37. }
  38. for (;;) {
  39. for (ui32 i = 0; i < SpinCount_; ++i) {
  40. if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
  41. return;
  42. SpinLockPause();
  43. }
  44. SequenceStore(UnshareFutex_, 1);
  45. if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
  46. AtomicStore(UnshareFutex_, 0);
  47. return;
  48. }
  49. FutexWait(UnshareFutex_, 1);
  50. }
  51. }
  52. void TLightRWLock::WaitForUntrappedAndAcquireRead() {
  53. if (AtomicFetchAdd(Counter_, -1) < 0)
  54. goto skip_lock_try;
  55. for (;;) {
  56. again:
  57. if (Y_UNLIKELY(AtomicFetchAdd(Counter_, 1) >= 0)) {
  58. return;
  59. } else {
  60. if (AtomicFetchAdd(Counter_, -1) >= 0)
  61. goto again;
  62. }
  63. skip_lock_try:
  64. if (AtomicLoad(UnshareFutex_) && (AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
  65. SequenceStore(UnshareFutex_, 0);
  66. FutexWake(UnshareFutex_, 1);
  67. }
  68. for (;;) {
  69. for (ui32 i = 0; i < SpinCount_; ++i) {
  70. SpinLockPause();
  71. if (AtomicLoad(Counter_) >= 0)
  72. goto again;
  73. if (AtomicLoad(TrappedFutex_) == 1)
  74. goto skip_store_trapped;
  75. }
  76. SequenceStore(TrappedFutex_, 1);
  77. skip_store_trapped:
  78. if (AtomicLoad(Counter_) < 0) {
  79. FutexWait(TrappedFutex_, 1);
  80. if (AtomicLoad(Counter_) < 0)
  81. goto again;
  82. } else if (AtomicLoad(TrappedFutex_)) {
  83. SequenceStore(TrappedFutex_, 0);
  84. FutexWake(TrappedFutex_, 0x7fffffff);
  85. }
  86. break;
  87. }
  88. }
  89. }
  90. #endif // _linux_