spin_wait.cpp 874 B

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. #include "spin_wait.h"
  2. #include "yield.h"
  3. #include "compat.h"
  4. #include "spinlock.h"
  5. #include <util/digest/numeric.h>
  6. #include <util/generic/utility.h>
  7. #include <atomic>
  8. namespace {
  9. unsigned RandomizeSleepTime(unsigned t) noexcept {
  10. static std::atomic<unsigned> counter = 0;
  11. const unsigned rndNum = IntHash(++counter);
  12. return (t * 4 + (rndNum % t) * 2) / 5;
  13. }
  14. // arbitrary values
  15. constexpr unsigned MIN_SLEEP_TIME = 500;
  16. constexpr unsigned MAX_SPIN_COUNT = 0x7FF;
  17. } // namespace
  18. TSpinWait::TSpinWait() noexcept
  19. : T(MIN_SLEEP_TIME)
  20. , C(0)
  21. {
  22. }
  23. void TSpinWait::Sleep() noexcept {
  24. ++C;
  25. if (C == MAX_SPIN_COUNT) {
  26. ThreadYield();
  27. } else if ((C & MAX_SPIN_COUNT) == 0) {
  28. usleep(RandomizeSleepTime(T));
  29. T = Min<unsigned>(T * 3 / 2, 20000);
  30. } else {
  31. SpinLockPause();
  32. }
  33. }