lightrwlock_test.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #include <library/cpp/threading/light_rw_lock/lightrwlock.h>
  2. #include <util/random/random.h>
  3. #ifdef _linux_
  4. // Light rw lock is implemented only for linux
  5. using namespace NS_LightRWLock;
  6. #include <pthread.h>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #define LIGHT
  10. #ifdef RWSPINLOCK
  11. #include <library/cpp/lwtrace/rwspinlock.h>
  12. #endif
  13. #define CHECK_LOGIC 1
  14. #define LOOPCOUNT 1000000
  15. #define RANRCOUNT 100
  16. #define THREADCOUNT 40
  17. #define WRITELOCKS 100
  18. #if defined(_MSC_VER)
  19. static int Y_FORCE_INLINE AtomicFetchAdd(volatile int& item, int value) {
  20. return _InterlockedExchangeAdd((&item, value);
  21. }
  22. #elif defined(__GNUC__)
  23. #else
  24. #error unsupported platform
  25. #endif
  26. class TPosixRWLock {
  27. public:
  28. TPosixRWLock() {
  29. }
  30. ~TPosixRWLock() {
  31. pthread_rwlock_destroy(&rwlock);
  32. }
  33. TPosixRWLock(const TPosixRWLock&) = delete;
  34. void operator=(const TPosixRWLock&) = delete;
  35. private:
  36. pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
  37. friend class TPosixRWShareLocker;
  38. friend class TPosixRWExclusiveLocker;
  39. };
  40. #if defined(LIGHT)
  41. TLightRWLock __attribute__((aligned(64))) rwlock;
  42. #elif defined(POSIX)
  43. TPosixRWLock rwlock;
  44. #elif defined(RWSPINLOCK)
  45. TRWSpinLock __attribute__((aligned(64))) rwlock;
  46. #else
  47. #error "define lock type"
  48. #endif
  49. volatile __attribute__((aligned(64))) int checkIt = 0;
  50. volatile int checkExcl = 0;
  51. class TPosixRWShareLocker {
  52. public:
  53. TPosixRWShareLocker(TPosixRWLock& lock)
  54. : LockP_(&lock)
  55. {
  56. pthread_rwlock_rdlock(&LockP_->rwlock);
  57. }
  58. ~TPosixRWShareLocker() {
  59. pthread_rwlock_unlock(&LockP_->rwlock);
  60. }
  61. TPosixRWShareLocker(const TPosixRWShareLocker&) = delete;
  62. void operator=(const TPosixRWShareLocker&) = delete;
  63. private:
  64. TPosixRWLock* LockP_;
  65. };
  66. class TPosixRWExclusiveLocker {
  67. public:
  68. TPosixRWExclusiveLocker(TPosixRWLock& lock)
  69. : LockP_(&lock)
  70. {
  71. pthread_rwlock_wrlock(&LockP_->rwlock);
  72. }
  73. ~TPosixRWExclusiveLocker() {
  74. pthread_rwlock_unlock(&LockP_->rwlock);
  75. }
  76. TPosixRWExclusiveLocker(const TPosixRWExclusiveLocker&) = delete;
  77. void operator=(const TPosixRWExclusiveLocker&) = delete;
  78. private:
  79. TPosixRWLock* LockP_;
  80. };
  81. template <typename TLocker, bool excl>
  82. static Y_FORCE_INLINE void Run() {
  83. TLocker lockIt(rwlock);
  84. #if defined(CHECK_LOGIC) && CHECK_LOGIC
  85. if (!excl && checkExcl == 1) {
  86. printf("there is a bug\n");
  87. }
  88. int result = AtomicFetchAdd(checkIt, 1);
  89. if (excl)
  90. checkExcl = 1;
  91. if (excl && result > 1)
  92. printf("there is a bug\n");
  93. #endif
  94. for (unsigned w = 0; w < RANRCOUNT; ++w)
  95. RandomNumber<ui32>();
  96. #if defined(CHECK_LOGIC) && CHECK_LOGIC
  97. if (excl)
  98. checkExcl = 0;
  99. AtomicFetchAdd(checkIt, -1);
  100. #endif
  101. }
  102. #ifdef LIGHT
  103. static void* fast_thread_start(__attribute__((unused)) void* arg) {
  104. for (unsigned q = 0; q < LOOPCOUNT; ++q) {
  105. char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
  106. if (excl)
  107. Run<TLightWriteGuard, 1>();
  108. else
  109. Run<TLightReadGuard, 0>();
  110. }
  111. return NULL;
  112. }
  113. #endif
  114. #ifdef POSIX
  115. static void* fast_thread_start(__attribute__((unused)) void* arg) {
  116. for (unsigned q = 0; q < LOOPCOUNT; ++q) {
  117. char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
  118. if (excl)
  119. Run<TPosixRWExclusiveLocker, 1>();
  120. else
  121. Run<TPosixRWShareLocker, 0>();
  122. }
  123. return NULL;
  124. }
  125. #endif
  126. #ifdef RWSPINLOCK
  127. static void* fast_thread_start(__attribute__((unused)) void* arg) {
  128. for (unsigned q = 0; q < LOOPCOUNT; ++q) {
  129. char excl = (RandomNumber<ui32>() % WRITELOCKS) == 0;
  130. if (excl)
  131. Run<TWriteSpinLockGuard, 1>();
  132. else
  133. Run<TReadSpinLockGuard, 0>();
  134. }
  135. return NULL;
  136. }
  137. #endif
  138. int main() {
  139. pthread_t threads[THREADCOUNT];
  140. for (unsigned q = 0; q < THREADCOUNT; ++q) {
  141. pthread_create(&(threads[q]), NULL, &fast_thread_start, NULL);
  142. }
  143. for (unsigned q = 0; q < THREADCOUNT; ++q)
  144. pthread_join(threads[q], NULL);
  145. return 0;
  146. }
  147. #else // !_linux_
  148. int main() {
  149. return 0;
  150. }
  151. #endif